MSSQL里怎么把多行数据合成一行,感觉挺实用的技巧分享
- 问答
- 2026-01-13 09:48:13
- 4
关于MSSQL里怎么把多行数据合并成一行,这确实是一个非常实用且经常被问到的技巧,想象一下这样的场景:你有一个订单表,一个订单对应多个产品,但你希望查询结果中每个订单只占一行,后面跟着这个订单下的所有产品名称,用逗号隔开,这种需求在生成报表、数据导出或前端显示时特别常见,下面我就分享几种最常用、最直接的方法。
最经典的方法:使用 FOR XML PATH
这个方法可以说是SQL Server中实现字符串聚合的“老将”了,非常灵活且强大,虽然名字里有XML,但我们完全可以把它当作一个纯粹的字符串拼接工具来用。
它的基本语法结构是这样的:
SELECT ... + ',' + ... FROM ... FOR XML PATH('')
我们来拆解一个具体的例子,假设我们有一张表叫 OrderDetails,里面有 OrderID 和 ProductName 两个字段,现在我们要把同一个 OrderID 下的所有 ProductName 合并到一起。

SELECT
OrderID,
STUFF((
SELECT ',' + ProductName
FROM OrderDetails AS inner_table
WHERE inner_table.OrderID = outer_table.OrderID
FOR XML PATH('')
), 1, 1, '') AS AllProducts
FROM OrderDetails AS outer_table
GROUP BY OrderID;
看起来有点复杂?别怕,我们一步步看:
- 核心部分:
SELECT ',' + ProductName FROM ... FOR XML PATH(''),这行代码会为每个OrderID循环执行。FOR XML PATH('')会把查询结果转换成XML格式,但因为我们在PATH中指定了空字符串,它不会生成任何XML标签,而是直接将所有行的,ProductName连接成一个长长的字符串,可能会先得到,苹果,香蕉,橘子这样的结果。 - 去掉开头的逗号:这就是
STUFF函数的作用了。STUFF(字符串, 开始位置, 要删除的字符长度, 要插入的字符串),我们得到的字符串第一个字符是多余的逗号,所以用STUFF(..., 1, 1, '')意思就是:从第一个字符开始,删掉1个字符(也就是那个逗号),然后插入一个空字符串(也就是不插入东西),这样就把开头的逗号干掉了,最终得到苹果,香蕉,橘子。 - 关联子查询:注意里面的
WHERE inner_table.OrderID = outer_table.OrderID,这叫关联子查询,它确保了我们在拼接字符串时,只拼接属于当前外层查询那个OrderID的产品。
这个方法非常可靠,几乎可以在所有版本的SQL Server中使用,根据微软官方文档的建议,这曾是早期版本中完成此类任务的标准方式。
现代更简洁的方法:STRING_AGG 函数(推荐)
如果你使用的SQL Server是2017版本或更高,那么恭喜你,你有了一种更简单、更直观、性能也通常更好的选择——STRING_AGG 函数,这个函数就是微软专门为解决“多行合并一行”这个问题而生的。

它的语法非常简单:
STRING_AGG(表达式, 分隔符)
还用上面的例子,用 STRING_AGG 来写就变得异常清晰:
SELECT
OrderID,
STRING_AGG(ProductName, ',') AS AllProducts
FROM OrderDetails
GROUP BY OrderID;
看,是不是简洁多了?!你不需要理解XML,也不需要复杂的子查询和STUFF函数,直接告诉SQL Server:请按 OrderID 分组,然后把每个组里的 ProductName 用逗号连接起来。
STRING_AGG 函数还支持一些有用的选项,比如你可以用 WITHIN GROUP (ORDER BY ...) 来指定拼接前对数据进行排序,这在某些场景下很重要,你想让产品名称按字母顺序排列:

SELECT
OrderID,
STRING_AGG(ProductName, ',') WITHIN GROUP (ORDER BY ProductName) AS AllProducts
FROM OrderDetails
GROUP BY OrderID;
根据微软Learn官方文档的介绍,STRING_AGG 在执行聚合字符串连接时是最高效的方法。
两种方法怎么选?
- 如果你的SQL Server是2017或更新版本,毫无疑问,直接使用
STRING_AGG,它写法简单,意图明确,不易出错,而且是官方推荐的标准做法。 - 如果你的服务器是2016或更老的版本,
FOR XML PATH就是你最好的朋友,虽然写法上绕一点,但它是经过无数项目验证的、可靠的解决方案。
一个重要的提醒:处理NULL值
在使用这两种方法时,都要注意被拼接的字段可能包含NULL值。ProductName 有NULL,无论是 FOR XML PATH 还是 STRING_AGG,都会忽略这个NULL值,不会在最终字符串里留下一个空位,但如果你希望将NULL值显示为某个默认文本(如‘未知产品’),你需要在拼接前先用 ISNULL 或 COALESCE 函数处理一下。
在 STRING_AGG 中:
STRING_AGG(ISNULL(ProductName, '未知产品'), ',')
总结一下
把多行数据合并成一行,核心思路就是“分组”和“字符串聚合”。FOR XML PATH 是功能强大的经典工具,而 STRING_AGG 则是为现代SQL Server量身定制的利器,掌握这两种方法,尤其是根据你的数据库版本灵活选择,就能轻松应对各种数据合并的需求,让你的查询结果更加清晰易读,希望这个分享对你有帮助!
本文由盘雅霜于2026-01-13发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:http://waw.haoid.cn/wenda/79856.html
