SQLSERVER 中的 ListAGG
Posted
技术标签:
【中文标题】SQLSERVER 中的 ListAGG【英文标题】:ListAGG in SQLSERVER 【发布时间】:2013-03-06 20:14:57 【问题描述】:我正在尝试在 SQLServer 中聚合一个“STRING”字段。我想在 Oracle 中找到与 LISTAGG 相同的函数。
你知道如何执行相同的功能或另一种方法吗?
例如,
Field A | Field B
1 | A
1 | B
2 | A
我希望这个查询的结果是
1 | AB
2 | A
【问题讨论】:
请为 DISTINCT 投票:feedback.azure.com/forums/908035-sql-server/suggestions/… 【参考方案1】:从SQL Server 2017 开始,可以使用STRING_AGG
函数,这大大简化了逻辑:
select FieldA, string_agg(FieldB, '') as data
from yourtable
group by FieldA
见SQL Fiddle with Demo
在 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 with Demo
【讨论】:
我想在子选择中插入一个 order by 子句。你知道怎么插入这个子句吗? @user1557642 你想点什么?你想要颠倒的值吗?您可以轻松添加ORDER BY
,请参阅此演示——sqlfiddle.com/#!3/0836c/7。在这种情况下,FieldA
的结果将显示 BA
@user1557642 你可以使用ORDER BY
,你只需要在子查询中包含一个GROUP BY
,看这个演示——sqlfiddle.com/#!3/0836c/7
这个答案不再好。当前版本的 SQL Server 具有 STRING_AGG,它执行相同的工作并且在我的测试中总是更快。
@Qwertie 答案仍然有效,但我已更新答案以包含 STRING_AGG 函数版本。【参考方案2】:
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 principle)
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;
【讨论】:
很好的答案 - 比标记的答案更简洁+还提到了其他 sql 方言。用于此的 sqlserver 语法非常不直观。我也很惊讶 select in stuff 周围的额外括号是必要的。 @manas_kumar 但是……你为什么使用 STUFF?这是不必要的。我错过了什么吗? @Ricardo_C STUFF 在这里被用来删除前导逗号。 要完整,这需要添加到sql server示例中:***.com/a/8856789它可以防止某些字符被XML标签替换。 @DanLenski 似乎不是这样,因为我现在在我的另一台显示器上成功引用了cte
,我想你没有正确构建你的查询?【参考方案3】:
在 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 中可用
【讨论】:
STRING_AGG / STRING_SPLIT 最近也被添加到 Azure SQL 数据库中,任何碰巧登陆该平台的人也可以使用。 注意:vNext 已命名为 SQL Server 2017 你知道如何使用 distinct c.name,所以所有连接的名称都是唯一的吗?【参考方案4】:这可能对某人也有用..
即对于数据分析师和数据分析类型的目的..(即不分组)..
在 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
【讨论】:
以上是关于SQLSERVER 中的 ListAGG的主要内容,如果未能解决你的问题,请参考以下文章