將同一群組內的多筆資料列,彙總為單一字串,欄位值以分隔符 (如逗號、分號) 區隔。常見於:標籤彙總、權限清單、明細匯總顯示。
STUFF((
SELECT ',' + ColumnName
FROM TableName
WHERE GroupCondition = Outer.GroupCondition
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
PATH('') 表示不產生包裹元素,直接輸出字串。,Value1,Value2,Value3。TYPE 時需此步驟)。DECLARE @T1 TABLE (
UserID INT,
UserName NVARCHAR(50),
CityName NVARCHAR(50)
);
INSERT INTO @T1 VALUES
(1, N'小明', N'上海'),
(2, N'小紅', N'北京'),
(3, N'小強', N'上海'),
(4, N'小美', N'北京'),
(5, N'小李', N'上海');
SELECT
CityName,
STUFF((
SELECT ',' + UserName
FROM @T1 sub
WHERE sub.CityName = main.CityName
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'), 1, 1, '') AS UserList
FROM @T1 main
GROUP BY CityName;
結果:
| CityName | UserList |
|---|---|
| 上海 | 小明,小強,小李 |
| 北京 | 小紅,小美 |
SELECT
main.CityName,
ca.UserList
FROM @T1 main
CROSS APPLY (
SELECT STUFF((
SELECT ',' + UserName
FROM @T1 sub
WHERE sub.CityName = main.CityName
ORDER BY UserName -- 可在這裡排序
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'), 1, 1, '') AS UserList
) ca
GROUP BY main.CityName, ca.UserList;
SELECT
CityName,
LEFT(UserList, LEN(UserList) - 1) AS UserList
FROM (
SELECT
CityName,
(SELECT UserName + ',' FROM @T1 WHERE CityName = main.CityName FOR XML PATH('')) AS UserList
FROM @T1 main
GROUP BY CityName
) t;
STUFF((
SELECT DISTINCT ',' + UserName -- 加 DISTINCT
FROM @T1 sub
WHERE sub.CityName = main.CityName
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
STUFF((
SELECT ',' + UserName
FROM @T1 sub
WHERE sub.CityName = main.CityName
ORDER BY UserID DESC -- 依 ID 遞減
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
STUFF((
SELECT ',' + UserName + ':' + CAST(Age AS VARCHAR(3))
FROM @T1 sub
WHERE sub.CityName = main.CityName
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
若欄位值可能包含 < > &,需改用 FOR XML PATH 的 TYPE 配合 .value (如上範例已示範),或使用 REPLACE 處理。
SELECT
CityName,
STRING_AGG(UserName, ',') WITHIN GROUP (ORDER BY UserName) AS UserList
FROM @T1
GROUP BY CityName;
WITHIN GROUP (ORDER BY ...) 內建排序。| 方法 | 適用版本 | 效能 | 建議 |
|---|---|---|---|
| STRING_AGG | 2017+ | ⭐⭐⭐⭐⭐ | 首選,原生最佳化 |
| STUFF + FOR XML PATH | 2005+ | ⭐⭐⭐ | 舊版本唯一選擇,加 TYPE + .value 防編碼 |
| CLR 聚合函數 | 2005+ | ⭐⭐⭐⭐ | 極大資料量、複雜邏輯時考慮 |
| 游標/迴圈 | 所有 | ⭐ | **嚴禁生產環境**,效能極差 |