表 Body(ID, BODY) 有重復 ID,需按 ID 分組將 BODY 值用逗號拼成單行:
ID | BODY
1 | aaaa
2 | bbbb
1 | cccccc
3 | ddddd
-- 期望結果
1 | aaaa,cccccc
2 | bbbb
3 | ddddd
SELECT DISTINCT a.ID,
STUFF((
SELECT ',' + BODY
FROM Body
WHERE ID = a.ID
FOR XML PATH(''), TYPE
).value('.','NVARCHAR(MAX)'), 1, 1, '') AS BODY
FROM Body a;
FOR XML PATH(''):將子查詢結果按行拼接,無標籤,產生 ,aaaa,cccccc 形式的 XML 片段。.value('.','NVARCHAR(MAX)'):將 XML 片段轉為標量字符串(兼容特殊字符 < > & 自動實體化)。STUFF(..., 1, 1, ''):刪除首字符逗號。DISTINCT:去重外層分組鍵。
SELECT ID, STRING_AGG(BODY, ',') AS BODY
FROM Body
GROUP BY ID;
更簡潔、性能更強、支持 WITHIN GROUP (ORDER BY ...) 排序。
ID 上建立索引。NVARCHAR(MAX) / VARCHAR(MAX)。STUFF + FOR XML PATH 是 2005-2016 時代的字符串聚合標準解法,至今仍廣泛運行於存量系統。新項目請直接使用 STRING_AGG,享受原生優化與簡潔語法。