查询在 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
我有这个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