SQL Server - 多列上的FOR XML PATH

时间:2017-07-03 06:23:23

标签: sql sql-server xml sql-server-2008

我正在使用SQL Server 2008。

我有一个项目表及其所属的类别。

-----------------------------------------------------------------
ItemId | Category1  | Category2  | Category3  | Category4
-----------------------------------------------------------------
1      | Val1, Val2 | Val3, Val4 | Val5, Val6 | Val7, Val8
1      | Val9       |            |            |     
1      | Val10      | Val11      |            |

* Edit1

表上没有索引,而ItemId不是主键。 每个项目可能属于多个类别。

我想从表中选择不同的ItemId,并为每列分隔逗号分隔所有可能的类别。

示例输出 -

------------------------------------------------------------------------------
ItemId | Category1               | Category2         | Category3  | Category4
------------------------------------------------------------------------------
1      | Val1, Val2, Val9, Val10 | Val3, Val4, Val11 | Val5, Val6 | Val7, Val8

我可以使用以下查询使用STUFF和FOR XML PATH实现此目的。但是,我看一下执行计划,看起来可能不是最好的方法。我为每个分类使用了4种不同的SELECT语句。它可以合并成一个吗? 我正在寻找最有效的查询来获得与以下查询相同的结果。

SELECT  DISTINCT
        t1.tblItemId,
        STUFF((
        SELECT DISTINCT ',' + t2.Category1
        FROM tblCategory t2
        WHERE t1.tblItemId = t2.tblItemId 
        FOR XML PATH ('')), 1, 1, '') AS Category1,
        STUFF((
        SELECT DISTINCT ',' + t2.Category2 
        FROM tblCategory t2
        WHERE t1.tblItemId = t2.tblItemId 
        FOR XML PATH ('')), 1, 1, '') AS Category2,        
        STUFF((
        SELECT DISTINCT ',' + t2.Category3 
        FROM tblCategory t2
        WHERE t1.tblItemId = t2.tblItemId 
        FOR XML PATH ('')), 1, 1, '') AS Category3,        
        STUFF((
        SELECT DISTINCT ',' + t2.Category4 
        FROM tblCategory t2
        WHERE t1.tblItemId = t2.tblItemId 
        FOR XML PATH ('')), 1, 1, '') AS Category4
FROM tblCategory t1
where t1.tblItemId IS NOT NULL

* Edit1 - 目前,逗号分隔的每一行中不存在多个值。我已经使用过它们,因为它可能会在将来出现,没有人会限制它。我正在使用公用表表达式创建一个临时表,其中包含可用于前端的所需输出。

1 个答案:

答案 0 :(得分:0)

您可以使用SQL CRL编写自己的STRING_AGG(出现在SQL 2016中)。 或使用现有的库(例如http://groupconcat.codeplex.com/