SQLSERVER中的ListAGG


Answers:


80

SQL Server 2017开始,该STRING_AGG功能可用,从而大大简化了逻辑:

select FieldA, string_agg(FieldB, '') as data
from yourtable
group by FieldA

参见带有演示的SQL Fiddle

在SQL Server中,您可以FOR XML PATH用来获取结果:

select distinct t1.FieldA,
  STUFF((SELECT distinct '' + t2.FieldB
         from yourtable t2
         where t1.FieldA = t2.FieldA
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,0,'') data
from yourtable t1;

参见带有演示的SQL Fiddle


我想在子选择中插入order by子句。您知道如何插入此子句吗?
user1557642 2013年

@ user1557642您想订购什么?是否要反转值?您可以轻松添加一个ORDER BY演示程序sqlfiddle.com/#!3/0836c/7。在这种情况下,结果FieldA将会显示BA
Taryn

实际上,我有10行要汇总。但是SQLServer在聚集之前进行字母排序。我想用我自己的参数(第三个字段)而不是字母顺序来聚合。
user1557642 2013年

3
@ user1557642您可以使用ORDER BY,只需GROUP BY在子查询中包含,请参见此演示-sqlfiddle.com/#!3/0836c/7
Taryn

中断带有特殊字符(如“ <”)的字符串;他们得到XML编码。根本不是解决方案。基于“ for xml path”的过时的,未记录的行为的总黑客。
Triynko '16

149

的MySQL

SELECT FieldA
     , GROUP_CONCAT(FieldB ORDER BY FieldB SEPARATOR ',') AS FieldBs
  FROM TableName
 GROUP BY FieldA
 ORDER BY FieldA;

Oracle和DB2

SELECT FieldA
     , LISTAGG(FieldB, ',') WITHIN GROUP (ORDER BY FieldB) AS FieldBs
  FROM TableName
 GROUP BY FieldA
 ORDER BY FieldA;

PostgreSQL的

SELECT FieldA
     , STRING_AGG(FieldB, ',' ORDER BY FieldB) AS FieldBs
  FROM TableName
 GROUP BY FieldA
 ORDER BY FieldA;

SQL服务器

SQL Server≥2017和Azure SQL

SELECT FieldA
     , STRING_AGG(FieldB, ',') WITHIN GROUP (ORDER BY FieldB) AS FieldBs
  FROM TableName
 GROUP BY FieldA
 ORDER BY FieldA;

SQL Server≤2016(包含CTE以鼓励DRY原则

  WITH CTE_TableName AS (
       SELECT FieldA, FieldB
         FROM TableName)
SELECT t0.FieldA
     , STUFF((
       SELECT ',' + t1.FieldB
         FROM CTE_TableName t1
        WHERE t1.FieldA = t0.FieldA
        ORDER BY t1.FieldB
          FOR XML PATH('')), 1, LEN(','), '') AS FieldBs
  FROM CTE_TableName t0
 GROUP BY t0.FieldA
 ORDER BY FieldA;

SQLite的

订购需要CTE或子查询

  WITH CTE_TableName AS (
       SELECT FieldA, FieldB
         FROM TableName
        ORDER BY FieldA, FieldB)
SELECT FieldA
     , GROUP_CONCAT(FieldB, ',') AS FieldBs
  FROM CTE_TableName
 GROUP BY FieldA
 ORDER BY FieldA;

无需订购

SELECT FieldA
     , GROUP_CONCAT(FieldB, ',') AS FieldBs
  FROM TableName
 GROUP BY FieldA
 ORDER BY FieldA;

5
很棒的答案-比标记的答案更简洁+还提到了其他sql方言。sqlserver的语法确实不直观。我也感到惊讶的是,在选择内容周围需要使用多余的括号。
JonnyRaa 2014年

@manas_kumar但是...为什么使用STUFF?没必要。我想念什么吗?
里卡多(Ricardo C)

@Ricardo_C STUFF在此处用于删除前导逗号。
DigitalDan

1
为了完整起见,需要将其添加到sql server示例中:stackoverflow.com/a/8856789它可以防止某些字符被XML标记替换。
Wouter

1
@DanLenski情况似乎并非如此,因为我现在正在cte另一台监视器上成功引用一个成功对象,我会以为您没有正确构建查询?
iamdave

20

在SQL Server 2017中添加了STRING_AGG

SELECT t.name,STRING_AGG (c.name, ',') AS csv
FROM sys.tables t
JOIN sys.columns c on t.object_id = c.object_id
GROUP BY t.name
ORDER BY 1

此外,STRING_SPLIT对于相反的情况也很有用,并且在SQL Server 2016中可用


2
STRING_AGG / STRING_SPLIT最近也被添加到Azure SQL数据库中,并且恰好适合该平台上的任何人。
布赖恩·乔登

4
注意:vNext已被命名为SQL Server 2017
Charles Burns

您知道如何使用不同的c.name,因此所有串联的名称都是唯一的吗?
谢尔盖·马柳丁

1

这也可能对某人有用。

即用于数据分析人员和数据分析的目的类型..(即未分组)。

SQL * Server 2017之前的String_agg函数存在..

(即仅返回一行..)

select distinct
SUBSTRING (
stuff(( select distinct ',' + [FieldB] from tablename order by 1 FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)') 
,1,0,'' ) 
,2,9999)
from 
    tablename 

例如,返回逗号分隔的值A,B

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.