將同一群組下多筆資料的特定欄位(如原因代碼、標籤、郵件地址)串聯成單一字串,以分隔符號分隔。典型應用:訂單多商品名稱合併、使用者多角色標籤聚合、錯誤代碼彙總。
CREATE FUNCTION dbo.ConcatReasons(@Standard VARCHAR(100))
RETURNS VARCHAR(8000)
AS BEGIN
DECLARE @Result VARCHAR(8000) = ''
SELECT @Result = @Result + ',' + Reason
FROM tb WHERE Standard = @Standard
RETURN STUFF(@Result, 1, 1, '')
END
缺點:逐列處理、無法平行化、效能差、無法利用索引、並發下易發生阻塞。
SELECT
Standard,
Amount,
Variation,
Status,
STUFF((
SELECT ',' + Reason
FROM tb t2
WHERE t2.Standard = t1.Standard
FOR XML PATH(''), TYPE
).value('.', 'VARCHAR(MAX)'), 1, 1, '') AS Reasons
FROM tb t1
GROUP BY Standard, Amount, Variation, Status
FOR XML PATH(''):產生無標籤 XML 片段,自動串聯TYPE 指令:回傳 XML 型別,避免特殊字元(& < >)被編碼.value('.', 'VARCHAR(MAX)'):將 XML 轉回字串STUFF(..., 1, 1, ''):移除首字分隔符SELECT
Standard,
STRING_AGG(Reason, ',') WITHIN GROUP (ORDER BY Reason) AS Reasons
FROM tb
GROUP BY Standard
原生聚合函數,語法簡潔、效能最佳、支援排序、自動處理 NULL。首選方案。
| 方法 | 適用版本 | 效能 | 維護性 | 建議 |
|---|---|---|---|---|
| 標量函數迴圈 | 所有版本 | 極差 | 差 | 棄用 |
| FOR XML PATH | 2005+ | 良好 | 中等 | 2016 及以前首選 |
| STRING_AGG | 2017+ | 最佳 | 最佳 | 現代首選 |
VARCHAR(MAX) / NVARCHAR(MAX)TYPE + .value 防編碼WITHIN GROUP (ORDER BY ...) 或子查詢加 ORDER BYSELECT
o.OrderID,
o.CustomerName,
STRING_AGG(p.ProductName, '; ') WITHIN GROUP (ORDER BY p.ProductName) AS Products
FROM Orders o
JOIN OrderDetails od ON o.OrderID = od.OrderID
JOIN Products p ON od.ProductID = p.ProductID
WHERE o.OrderDate >= '2024-01-01'
GROUP BY o.OrderID, o.CustomerName