查询在 SQL 服务器中填充重复记录?

Query to stuff duplicate records in SQL Server?

我有这个table:

   +----------+----------+---------+-----------------------------------+
| Class A  | Class  B | Class C | Result_XML                        |
+----------+----------+---------+-----------------------------------+
| SUPER    | PREMIUM  | A       | <Array> <Ser ref="RF124" r="200”> |
| ECONOMIC | SEMI     | A       | <Array> <Ser ref="RF124" r="200”> |
| SUPER    | PREMIUM  | A       | <Array> <Ser ref="RF144" r="500”> |
| SUPER    | NA       | B       | <Array> <Ser ref="RF124" r="200”> |
| ECONOMIC | SEMI     | A       | <Array> <Ser ref="RF154" r="200”> |
| SUPER    | PREMIUM  | C       | <Array> <Ser ref="RF124" r="100”> |
+----------+----------+---------+-----------------------------------+

而且,我一直试图得到的是如下所示:

+----------+---------+--------+---------+
|  ClassA  | ClassB  | ClassC | Result  |
+----------+---------+--------+---------+
| SUPER    | PREMIUM | A      | 200,500 |
| ECONOMIC | SEMI    | A      |     200 |
| SUPER    | NA      | B      |     200 |
| SUPER    | PREMIUM | C      |     100 |
+----------+---------+--------+---------+

基本上,上面是来自第一个 table 的不同记录列表,在最后一列中具有相同的结果,如果不同,则将结果填充到同一行中,就像第一个示例一样。到目前为止,我想出了以下但显然没有用。提前感谢您的帮助:

SELECT DISTINCT
    ClassA, ClassB, ClassC,
    Result = (STUFF((Select Distinct ',' + E1.RESULT_XML.value('(/Array/Ser/@r)[1]', 'varchar(max)')  
                     From listtable E2 
                     Where E1.ClassA = E2.ClassA 
                       And E1.ClassB = E2.ClassB 
                       And E1.ClassC = E2.ClassC
                     FOR XML PATH(''), TYPE, ROOT).value('root[1]','nvarchar(max)'),1,1,''))
FROM 
    listtable E1 

您应该在内容查询中使用 E2.ResultXml 而不是 E1.ResultXml。

DECLARE @T TABLE (ClassA NVARCHAR(50), ClassB NVARCHAR(50), ClassC NVARCHAR(50), ResultXML NVARCHAR(300))

INSERT @T SELECT 'SUPER','PREMIUM'  ,'A','200'--'<Array> <Ser ref="RF124" r="200”>' 
INSERT @T SELECT 'ECONOMIC','SEMI'  ,'A','200'--'<Array> <Ser ref="RF124" r="200”>' 
INSERT @T SELECT 'SUPER','PREMIUM'  ,'A','500'--'<Array> <Ser ref="RF144" r="500”>' 
INSERT @T SELECT 'SUPER','NA'       ,'B','200'--'<Array> <Ser ref="RF124" r="200”>' 
INSERT @T SELECT 'ECONOMIC','SEMI'  ,'A','200'--'<Array> <Ser ref="RF154" r="200”>' 
INSERT @T SELECT 'SUPER','PREMIUM'  ,'C','100'--'<Array> <Ser ref="RF124" r="100”>' 

SELECT * FROM @T


SELECT 
    ClassA,ClassB,ClassC,
    Result = (STUFF((Select  DISTINCT ',' + E2.RESULTXML  
                     From @T E2 
                     Where E1.ClassA = E2.ClassA 
                       And E1.ClassB = E2.ClassB 
                       And E1.ClassC = E2.ClassC
                     FOR XML PATH('')),1,1,''))
FROM 
    @T E1 
GROUP BY
    ClassA, ClassB, ClassC

收益率--->

ClassA      ClassB     ClassC  Result
ECONOMIC    SEMI       A       200
SUPER       NA         B       200
SUPER       PREMIUM    A       200,500
SUPER       PREMIUM    C       100
;with cte( ClassA  , ClassB , ClassC , Result_XML)
AS
(
SELECT 'SUPER'    , 'PREMIUM'  , 'A'       , '<Array> <Ser ref="RF124" r="200”>' Union all 
SELECT 'ECONOMIC' , 'SEMI'     , 'A'       , '<Array> <Ser ref="RF124" r="200”>' Union all 
SELECT 'SUPER'    , 'PREMIUM'  , 'A'       , '<Array> <Ser ref="RF144" r="500”>' Union all 
SELECT 'SUPER'    , 'NA'       , 'B'       , '<Array> <Ser ref="RF124" r="200”>' Union all 
SELECT 'ECONOMIC' , 'SEMI'     , 'A'       , '<Array> <Ser ref="RF154" r="200”>' Union all 
SELECT 'SUPER'    , 'PREMIUM'  , 'C'       , '<Array> <Ser ref="RF124" r="100”>' 
)

,Result AS (
    SELECT ClassA
        ,ClassB
        ,ClassC
        ,CAST(REPLACE(RIGHT(Result_XML, 5), '”>', '') AS INT) AS Result_XML
    FROM cte
    )

SELECT DISTINCT ClassA
    ,ClassB
    ,ClassC
    ,STUFF((
            SELECT DISTINCT ', ' + CAST(i.Result_XML AS VARCHAR(10))
            FROM Result i
            WHERE i.ClassA = o.ClassA
                AND i.ClassB = o.ClassB
                AND i.ClassC = o.ClassC
            FOR XML PATH('')
            ), 1, 1, '') AS Result
FROM Result o
ORDER BY ClassC
    ,Result DESC

输出

+----------+---------+--------+---------+
|  ClassA  | ClassB  | ClassC | Result  |
+----------+---------+--------+---------+
| SUPER    | PREMIUM | A      | 200,500 |
| ECONOMIC | SEMI    | A      |     200 |
| SUPER    | NA      | B      |     200 |
| SUPER    | PREMIUM | C      |     100 |
+----------+---------+--------+---------+

我有解决问题的方法,但我相信它可以更有效地解决。

SELECT
    ClassA
    ,ClassB
    ,ClassC
    ,Result = (STUFF((SELECT DISTINCT
            ',' + CAST(E1.Result AS XML).value('(/Array/Ser/@r)[1]', 'varchar(max)')
        FROM [OrchestratorNotifications].[dbo].[Kuko] E2
        WHERE E1.ClassA = E2.ClassA
        AND E1.ClassB = E2.ClassB
        AND E1.ClassC = E2.ClassC
        FOR XML PATH (''), TYPE, ROOT)
    .value('root[1]', 'nvarchar(max)'), 1, 1, '')) INTO #tmp1
FROM [OrchestratorNotifications].[dbo].[Kuko] E1
ORDER BY ClassA
    ,ClassB
    ,ClassC

SELECT ClassA
    ,ClassB
    ,ClassC
    ,Result FROM (
SELECT *,ROW_NUMBER() OVER( PARTITION BY ClassA,ClassB,ClassC ORDER BY ClassA,ClassB,ClassC,w DESC) AS r1 FROM( 
SELECT
    ClassA
    ,ClassB
    ,ClassC
    ,o.Result,
    o.w, 
    ROW_NUMBER() OVER( PARTITION BY ClassA,ClassB,ClassC,o.w  ORDER BY ClassA,ClassB,ClassC,o.w) AS rownum
FROM #tmp1 a
CROSS APPLY (SELECT
        CASE
            WHEN a.Result = b.Result THEN a.Result
            ELSE a.Result + ',' + b.Result
        END Result,
            CASE
            WHEN CAST( a.Result AS INT) = CAST( b.Result AS INT) THEN  CAST( a.Result AS INT) 
            ELSE CAST( a.Result AS INT)  + CAST( b.Result AS INT) 
        END w
    FROM #tmp1 b
    WHERE a.ClassA = b.ClassA
    AND a.ClassB = b.ClassB
    AND a.ClassC = b.ClassC) o
    )y 
    where y.rownum=1
    )d 
    WHERE d.r1=1
    ORDER BY d.ClassC

DROP TABLE #tmp1