我将SQL Server报表应用程序中的逗号分隔字段替换为多对多关系。尚无法替换应用程序代码,因此我需要派生当前期望的同一CSV列。过去我曾经使用过FOR XML PATH
技巧,它似乎是一种基于集的快速解决方案,应该易于实现。
我当前的查询如下:
SELECT
Report = rr.Report_ID,
RoleList = STUFF((SELECT ', ' + r.[Name] AS [text()]
FROM [dbo].[Role] r
WHERE r.Role_ID = rr.Role_ID
FOR XML PATH ('')), 1, 1, '')
FROM
[dbo].ReportRole rr
ORDER BY
rr.Report_ID;
我期望的是:
Report RoleList
--------------------------------------------------------------------
2 Senior Application Developer
3 Senior Application Developer, Manager Information Systems
但是我得到的却是这样:
Report RoleList
--------------------------------------
2 Senior Application Developer
3 Senior Application Developer
3 Manager Information Systems
我正在使用SQL Server2017。此版本不支持以前版本的XML-to-CSV hack?
答案 0 :(得分:0)
具有一个名为“ ReportRole”的表表示在您的案例中Report与Role之间的链接表。如果是这样,则可以将ReportRole表作为内部查询的一部分,并将报告ID保留在外部查询中:
SELECT
Report = rpt.Report_ID,
RoleList = STUFF((SELECT ', ' + r.[Name] AS [text()]
FROM [dbo].[Role] r
JOIN [dbo].ReportRole rr
ON r.Role_ID = rr.Role_ID
WHERE rr.Report_ID = rpt.Report_ID
FOR XML PATH ('')), 1, 1, '')
FROM
[dbo].Report rpt
ORDER BY
rpt.Report_ID;
答案 1 :(得分:0)
您已经用 SQL-Server 2017 标记了问题,然后问:
此版本不支持以前版本中的XML-to-CSV黑客吗?
是的,确实可以做到(正如Paurian的回答告诉你的那样),但效果更好:This version supports STRING_AGG()
:
不知道您的表我设置了一个迷你模型来模拟您的问题(根据您的表已规范化,联接表是简单的多对多ID映射< / em>):
两个表之间有一个m:n
映射表
DECLARE @mockupA TABLE(ID INT,SomeValue VARCHAR(10));
INSERT INTO @mockupA VALUES(1,'A1'),(2,'A2');
DECLARE @mockupB TABLE(ID INT,SomeValue VARCHAR(10));
INSERT INTO @mockupB VALUES(1,'B1'),(2,'B2');
DECLARE @mockupMapping TABLE(ID_A INT,ID_B INT);
INSERT INTO @mockupMapping VALUES(1,1),(1,2),(2,2);
-查询将简单地连接这些表,然后将GROUP BY
与STRING_AGG()
一起使用。 WITHIN GROUP
子句允许您确定串联字符串的排序顺序。
SELECT a.ID,a.SomeValue
,STRING_AGG(b.SomeValue,', ') WITHIN GROUP(ORDER BY b.ID) AS B_Values
FROM @mockupA a
INNER JOIN @mockupMapping m ON a.ID=m.ID_A
INNER JOIN @mockupB b ON b.ID=m.ID_B
GROUP BY a.ID,a.SomeValue;
结果
ID SomeValue B_Values
1 A1 B1, B2
2 A2 B2