将行值合并到CSV中(也称为SQL Server组)

将行值合并到CSV中(也称为SQL Server组),sql,sql-server,Sql,Sql Server,我有一张像这样的桌子: EntityID AttributeID OptionText 5016 20 Paintings 5044 18 Female 5060 48 M 5060 48 F 5060 49 Apple 5060 49 Banana 5060 49 C

我有一张像这样的桌子:

EntityID   AttributeID  OptionText
5016       20           Paintings
5044       18           Female
5060       48           M
5060       48           F
5060       49           Apple
5060       49           Banana
5060       49           Cat
我想创建一个视图,该视图将显示:

5016    20   Paintings
5044    18   Female
5060    48   M,F
5060    49   Apple, Banana, Cat
表示每个实体上的属性值应以逗号分隔显示

选项的数量可以变化


感谢您的帮助

对于每对
EntityID,AttributeID
使用XML路径技巧生成CSV

 SELECT
    M.EntityID, M.AttributeID,
    SUBSTRING(CAST(foo.bar AS varchar(8000)), 2, 7999) AS Options
FROM
    (
    SELECT DISTINCT EntityID, AttributeID
    FROM MyTable
    ) M
    CROSS APPLY
    (
    SELECT
        ',' + OptionText
    FROM
        MyTable M2
    WHERE
        M.EntityID = M2.EntityID AND M.AttributeID= M2.AttributeID
    FOR XML PATH ('')
    ) foo(bar)
尝试下面的代码(我已经包含了所有的测试SQL,所以您不必在实时数据上练习)。您可以在此处查看工作示例:


我用3种不同的方法做了一些测试:


希望能有所帮助。

STUFF((…),1,2,,)
相比,
子字符串
CAST
之间是否有明显的性能差异?@Seph:marginal,不知道哪种方式。大部分资源和时间将是连接和XML处理。没有删除第一个逗号。感谢您解决了查询,但我仍然面临性能问题。该表将有超过100万条记录。在这种情况下,即使只获取几条记录,所花费的时间也超过2秒。@Kamal Deep Singh:那么您的索引就有问题了。问一个关于表架构和索引的新问题。@gbn实际上问题在于我向您展示的表实际上是一个视图。我没有应用自己的索引。如果由sql server提供,则索引将是默认的。实际上,我正在应用一个类似于EAV模型的模型。在本例中,我需要这样一个条件。该查询非常有用,但我仍然面临性能问题。该表将有超过100万条记录。在这种情况下,即使只获取几条记录,所花费的时间也超过2秒。因为这是我们的一项经常性任务,我们最终把它变成了一个类似于您的方法#1的函数。xml路径技巧也很有效,但该函数使SQL更易于阅读。
--Set up test table
CREATE TABLE #Table1 (EntityID INT, AttributeID INT, OptionText VARCHAR(50))

INSERT INTO #Table1
SELECT  5030, 48, 'M'

INSERT INTO #Table1
SELECT  5030, 48, 'F'

--Begin actual working SQL          
SELECT      T1.EntityID,
            T1.AttributeID,
            STUFF(( SELECT    ', ' + T2.OptionText
                    FROM      #Table1 T2
                    WHERE     T2.AttributeID = T1.AttributeID
                    AND       T2.EntityID = T1.EntityID
                    FOR XML PATH('')
                  ), 1, 2, '') [Attributes]
FROM        #Table1 T1
GROUP BY    T1.EntityID, T1.AttributeID

DROP TABLE #Table1