【问题标题】:Concatenate multiple rows into one row将多行连接成一行
【发布时间】:2013-04-29 21:25:44
【问题描述】:

我刚刚在 SQL Server 上学习 SQL。我需要将多行连接成一列。我已经查找了示例,但没有找到可以满足我需求的示例。

Country     ProjectTA   Complexity TID  Sites   Inits   Name
United States A8022 Obesity Low  4692   69  JT  AD
United States A8022 Obesity Low  4692   69  jpni    CBM Budget
United States A8022 Obesity Low  4692   69  PIHR    AD
United States A8022 Obesity Low  4692   69  jpni    CBM Budget
United States A8022 Obesity Low  4692   69  hale    ePublishing Group
United States S8033 CNS Medium   5423   69  ShyP    CBM Payment
United States S8033 CNS Medium   5423   69  dedu    ePublishing Group
United States S8033 CNS Low  5423   69  AHrp    ePublishing Group

我想按 Name 连接行,并用 ',' 列出 Inits

United States A8022 Obesity Low 4692    69 JT,PIHR  AD
United States A8022 Obesity Low 4692    69 jpni, PIHR   CBM Budget
United States A8022 Obesity Low 4692    69 hale          ePublishing Group
United States S8033 CNS Medium  5423    69 ShyP          CBM Payment
United States S8033 CNS Medium  5423    69 dedu, Ahrp   ePublishing Group

任何帮助将不胜感激。非常感谢。

【问题讨论】:

  • 我不知道你什么时候想要逗号后面的空格,什么时候不想要。有什么区别?

标签: sql sql-server tsql


【解决方案1】:

很遗憾,SQL Server 没有生成逗号分隔列表的简单功能,您必须实现 FOR XML PATH 才能获取列表。

有几种方法可以做到这一点,你可以使用STUFFFOR XML PATH

select distinct t1.country,
  t1.ProjectTA, 
  t1.Complexity,
  t1.TID,
  t1.Sites,
  STUFF(
         (SELECT ', ' + t2.Inits
          FROM yt t2
          where t1.Country = t2.Country
            and t1.ProjectTA = t2.ProjectTA
            and t1.TID = t2.TID
            and t1.Sites = t2.Sites
            and t1.name = t2.name
          FOR XML PATH (''))
          , 1, 1, '')  AS inits,
  t1.name
from yt t1;

SQL Fiddle with demo

或者你可以使用CROSS APPLYFOR XML PATH

select distinct t1.country,
  t1.ProjectTA, 
  t1.Complexity,
  t1.TID,
  t1.Sites, 
  left(t2.inits, len(t2.inits)-1) inits,
  t1.name
from yt t1
cross apply
(
  select t2.Inits + ', '
  from yt t2
  where t1.Country = t2.Country
    and t1.ProjectTA = t2.ProjectTA
    and t1.TID = t2.TID
    and t1.Sites = t2.Sites
    and t1.name = t2.name
  FOR XML PATH('')
) t2 (inits);

SQL Fiddle with Demo。这些都产生了结果:

|       COUNTRY | PROJECTTA |  COMPLEXITY |  TID | SITES |      INITS |              NAME |
-------------------------------------------------------------------------------------------
| United States |     A8022 | Obesity Low | 4692 |    69 |       hale | ePublishing Group |
| United States |     A8022 | Obesity Low | 4692 |    69 | jpni, jpni |        CBM Budget |
| United States |     A8022 | Obesity Low | 4692 |    69 |   JT, PIHR |                AD |
| United States |     S8033 |     CNS Low | 5423 |    69 | dedu, AHrp | ePublishing Group |
| United States |     S8033 |  CNS Medium | 5423 |    69 | dedu, AHrp | ePublishing Group |
| United States |     S8033 |  CNS Medium | 5423 |    69 |       ShyP |       CBM Payment |

【讨论】:

    【解决方案2】:

    要在 SQL Server 中执行此操作,您需要将字符串连接在一起作为聚合函数。不幸的是,SQL Server 没有group_concat()listagg() 或一些相关功能。下面是 SQL Server 中的方法:

    select Country, ProjectTA, Complexity, TID,
           stuff((select ', '+Inits
                  from t t2
                  where t2.Name = t.Name and
                        t2.country = t.country and
                        t2.ProjectTA = t.ProjectTA and
                        t2.Tid = t.Tid
                  for xml path(''), type
                 ).value('.','nvarchar(max)'), 1, 2, ''
                ) as InitsList,
           Name
    from t
    group by country, ProjectTA, Complexity, TID, name;
    

    您似乎不仅仅按名称进行分组,因此我将除 inits 之外的所有字段都包含在该行中。

    【讨论】:

    • 尝试始终检查您的工作并使用FOR XML..TYPE 表单作为一般规则。不够聪明,无法进行 SQL Server 连接的新手可能很难理解为什么他们会在您的代码中获得 Msg 512, Level 16, State 1, Line 1: Subquery returned more than 1 value.。另请注意,对于 ', '(2 字符前缀),您需要使用 STUFF 删除 2 个字符。
    • @RichardTheKiwi 。 . .万分感谢。我已经离开我的电脑一个小时意识到我在查询中犯了这两个错误(在stuff() 上省略了for xml path2
    猜你喜欢
    • 2017-06-19
    • 2011-06-24
    • 1970-01-01
    • 2022-11-23
    • 2023-01-15
    • 1970-01-01
    • 2016-06-29
    • 2021-05-06
    • 1970-01-01
    相关资源
    最近更新 更多