如何用GROUP BY子句获取每组所有记录?SQL分组拼接需求求助
解决方案
嘿,你的需求是把同一部门下的员工姓名合并成逗号分隔的字符串对吧?这个问题在SQL里很常见,咱们直接上靠谱的解决方法:
方法一:使用STRING_AGG(SQL Server 2017及以上版本)
这是微软官方提供的字符串聚合函数,专门用来处理这类分组拼接场景,语法简洁又高效:
SELECT DepartmentId, STRING_AGG(EmployeeName, ', ') AS EmployeeNames FROM EmployeeTable GROUP BY DepartmentId;
简单解释下:
STRING_AGG(要拼接的字段, 分隔符)会自动把同一分组(这里是DepartmentId)下的所有EmployeeName用指定分隔符连接起来- 完全符合GROUP BY的规则,不会出现你之前遇到的语法错误
方法二:兼容旧版本SQL Server的STUFF + FOR XML PATH方法
如果你的SQL Server版本低于2017,没法用STRING_AGG,可以用这个经典的拼接方案:
SELECT t1.DepartmentId, STUFF( (SELECT ', ' + t2.EmployeeName FROM EmployeeTable t2 WHERE t2.DepartmentId = t1.DepartmentId FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, '' ) AS EmployeeNames FROM EmployeeTable t1 GROUP BY t1.DepartmentId;
拆解下逻辑:
- 子查询
(SELECT ', ' + t2.EmployeeName ... FOR XML PATH(''), TYPE)会把同一部门的员工姓名拼接成, A, B这类带前缀分隔符的字符串 STUFF函数用来去掉开头多余的,(从第1个字符开始,删除2个字符,替换为空字符串)TYPE.value('.', 'NVARCHAR(MAX)')是为了避免XML自动转义特殊字符(比如&变成&)
为什么你原来的查询不行?
你之前用(select EmployeeName for json path)的问题在于:
- 这个子查询没有关联外层的
DepartmentId,会把所有员工的姓名都查出来,而不是当前分组的员工 - GROUP BY要求非分组列必须用聚合函数包裹,你的写法里
EmployeeName既不在GROUP BY里,也没有用聚合函数,所以会触发语法错误
内容的提问来源于stack exchange,提问作者Mewo
相关产品推荐
相关产品推荐

