SQL Server中如何合并同NAME多行数据并统计数量
解决SQL Server分组聚合字符串并统计数量的问题
你要实现的是按NAME分组,统计每组记录数,同时把同组的TITLE拼接成逗号分隔的字符串对吧?你现有的语句里STUFF(TITLE)写法不对,因为STUFF需要配合字符串聚合的逻辑来用,下面根据你的SQL Server版本给两种可行方案:
方案1:SQL Server 2017+ 用官方聚合函数(推荐)
从2017版本开始,SQL Server提供了STRING_AGG这个专门做字符串聚合的函数,写起来非常简洁:
SELECT NAME, COUNT(ID) AS COUNT, STRING_AGG(TITLE, ', ') AS TITLE FROM TABLE_X GROUP BY NAME ORDER BY NAME;
简单解释下:
STRING_AGG(TITLE, ', '):把同一NAME下的所有TITLE用「逗号+空格」拼接成一个字符串COUNT(ID):统计每组的记录数,这里用COUNT(*)也可以,只要ID没有空值就行GROUP BY NAME:必须按NAME分组,否则聚合函数没法生效
方案2:SQL Server 2016及更早版本 用XML拼接方法
如果你的数据库版本比较老,没有STRING_AGG,就用经典的STUFF + FOR XML PATH写法:
SELECT t.NAME, COUNT(t.ID) AS COUNT, STUFF( (SELECT ', ' + x.TITLE FROM TABLE_X x WHERE x.NAME = t.NAME FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, '' ) AS TITLE FROM TABLE_X t GROUP BY t.NAME ORDER BY t.NAME;
这个写法的逻辑:
- 子查询里通过
FOR XML PATH('')把同NAME的TITLE前面加上,,拼成一个带前缀的字符串 TYPE.value('.', 'NVARCHAR(MAX)')把XML格式的结果转成普通字符串STUFF(..., 1, 2, ''):去掉字符串开头多余的,(因为第一个TITLE前面也会带这个前缀,所以从第1位开始删2个字符)- 外层的
GROUP BY和COUNT负责统计每组的数量
测试结果
用你给出的测试数据:
ID NAME TITLE
01 Bob Cat
02 Bob Bat
03 Tom Mat
执行上面任意一种方案,都会得到你想要的结果:
NAME COUNT TITLE
Bob 2 Cat, Bat
Tom 1 Mat
内容的提问来源于stack exchange,提问作者1.618




