SQL Server中关联表并将子表数据合并为单行逗号分隔值
解决SQL Server中主表关联子表并合并多行城市数据的问题
嘿,这个需求在SQL Server里其实很好实现,分两种场景给你详细说明,保证能得到你想要的输出结果:
方法一:SQL Server 2017+ 版本(推荐)
从SQL Server 2017开始,官方提供了STRING_AGG()这个专门用于字符串聚合的函数,用它来合并子表的城市数据非常简洁:
SELECT t1.ID, t1.Name, STRING_AGG(t2.CITY, ',') WITHIN GROUP (ORDER BY t2.CITY) AS CITY FROM 表1 t1 LEFT JOIN 表2 t2 ON t1.ID = t2.Tlb1_ID GROUP BY t1.ID, t1.Name ORDER BY t1.ID;
代码说明:
LEFT JOIN:确保主表表1的所有行都被保留,哪怕子表表2没有匹配的记录,这是实现无匹配行显示NULL的关键STRING_AGG(t2.CITY, ','):把每个主表行对应的子表CITY值用逗号分隔合并成一个字符串WITHIN GROUP (ORDER BY t2.CITY):可选参数,用来让合并后的城市按字母顺序排列,不需要排序的话可以直接去掉这部分- 当子表没有匹配行时,
STRING_AGG()会自动返回NULL,完全符合你的需求
执行后得到的结果和你期望的完全一致:
| ID | Name | CITY |
|---|---|---|
| 1 | A | ZZ,XX |
| 2 | B | GG,HH |
| 3 | C | JJ |
| 4 | D | NULL |
| 5 | E | NULL |
方法二:SQL Server 2016及更早版本
如果你的SQL Server版本比较老,不支持STRING_AGG(),可以用经典的FOR XML PATH拼接方法:
SELECT t1.ID, t1.Name, STUFF( (SELECT ',' + t2.CITY FROM 表2 t2 WHERE t2.Tlb1_ID = t1.ID FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '') AS CITY FROM 表1 t1 ORDER BY t1.ID;
代码说明:
- 子查询通过
FOR XML PATH('')把匹配的CITY值拼接成带逗号前缀的字符串(比如,ZZ,XX) STUFF()函数:用来去掉字符串开头的第一个逗号,得到干净的ZZ,XX格式- 当子表没有匹配行时,子查询返回空,
STUFF()会返回NULL,同样满足需求
内容的提问来源于stack exchange,提问作者Sunil Sharma




