【问题标题】:How do I join two tables and create an additional column with comma seperated values如何连接两个表并使用逗号分隔值创建一个附加列
【发布时间】:2020-03-05 21:32:59
【问题描述】:

除了 CRUD 查询之外,我对 SQL 没有太多经验;如果这是微不足道的,请原谅我。我正在尝试连接两个表并在结果中创建一个附加列,其中包含一系列逗号分隔值。

表 1

表 2

我可以使用从表 2 中获取逗号分隔值

DECLARE @tmp varchar(MAX)
SET @tmp = ''
SELECT @tmp = @tmp + CONVERT(VARCHAR(10), [materialTypeID])  + ', '
FROM [industryActivityMaterials] 
WHERE typeID = 1145 AND activityID =  1
SELECT SUBSTRING(@tmp, 0, LEN(@tmp)) AS materialsRequired

我不知道如何在typeID 上将这些表连接在一起以包含一组包含materialsReguired 列的结果。

【问题讨论】:

    标签: sql sql-server string tsql join


    【解决方案1】:

    您可以加入、聚合和使用聚合函数string_agg() 来生成逗号分隔的列表。此功能自 SQL Server 2017 起可用。

    select 
        t1.typeID, 
        t1.activityID,
        t1.activityName,
        t.Blueprint,
        t1.productTypeID,
        t1.ProductName,
        string_agg(t2.materialTypeID, ',') 
            within group (order by t2.materialTypeID) materialTypeIDs
    from 
        table1 t1
        inner join table2 t2
            on  t2.typeID = t1.typeID
            and t2.activityID = t1.activityID
    group by
        t1.typeID, 
        t1.activityID,
        t1.activityName,
        t.Blueprint,
        t1.productTypeID,
        t1.ProductName
    

    【讨论】:

      【解决方案2】:

      2016 sql server版本以下可以使用xml路径按字符串concat分组

      SELECT 
        T1.typeId,
        STUFF((
          SELECT ', ' + materialTypeID 
          FROM Table2 T2 
          WHERE (T2.typeId = T1.typeId) 
          FOR XML PATH(''),TYPE).value('(./text())[1]','VARCHAR(MAX)')
        ,1,2,'') AS materialsRequired
      FROM Table1 T1
      GROUP BY T1.typeId
      
      

      超过 sql server 2016 版本,您可以使用string_agg

      STRING_AGG (Transact-SQL) - SQL Server | Microsoft Docs

      【讨论】:

        【解决方案3】:

        请注意,无论采用何种方法,您都可能会发现相关子查询比大聚合更简单:

        select t1.*,
               (select string_agg(t2.materialTypeID, ',') within group (order by t2.materialTypeID)
                from table2 t2
                where t2.typeID = t1.typeID and
                      t2.activityID = t1.activityID
               ) as materialTypeIds
        from table1 t1;
        

        或者:

        select t1.*,
               stuff( (select concat(',', t2.materialTypeID) 
                       from table2 t2
                       where t2.typeID = t1.typeID and
                             t2.activityID = t1.activityID
                       for xml path ('')
                      ), 1, 1, ''
                    ) as materialTypeIds
        from table1 t1;
        

        一般来说,避免外部聚合可以提高性能,尤其是在table2(typeID, activityId) 上有索引的情况下。

        【讨论】:

        • 谢谢戈登。我也会试试你的方法。
        猜你喜欢
        • 2013-10-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-15
        • 2019-05-04
        • 2021-10-13
        • 2019-06-01
        相关资源
        最近更新 更多