來源表 EE:
| 日期 | 數量 | 物品 |
|---|---|---|
| 1月1日 | 200 | A |
| 1月1日 | 300 | A |
| 1月2日 | 100 | B |
| 1月3日 | 200 | A |
期望輸出:
| 物品 | 1月1日 | 1月2日 | 1月3日 |
|---|---|---|---|
| A | 500 | 0 | 200 |
| B | 0 | 100 | 0 |
DECLARE @sql NVARCHAR(MAX) = N'SELECT [物品]';
-- 1. 動態產生彙總欄位清單
SELECT @sql = @sql + N', SUM(CASE [日期] WHEN ''' + [日期] + ''' THEN [數量] ELSE 0 END) AS [' + [日期] + ']'
FROM (SELECT DISTINCT [日期] FROM EE) AS Dates;
-- 2. 完成 GROUP BY 子句
SET @sql = @sql + N' FROM EE GROUP BY [物品]';
-- 3. 執行
EXEC sp_executesql @sql;
DISTINCT 日期 迴圈組裝 SUM(CASE...) 運算式,解決「欄名不固定」問題。CASE WHEN 日期 = '目標日期' THEN 數量 ELSE 0 END 將長表轉寬表。EXEC(@sql) (計畫重用、防注入)。
SELECT 物品,
ISNULL([1月1日], 0) AS [1月1日],
ISNULL([1月2日], 0) AS [1月2日],
ISNULL([1月3日], 0) AS [1月3日]
FROM (
SELECT 物品, 日期, 數量 FROM EE
) AS SourceTable
PIVOT (
SUM(數量) FOR 日期 IN ([1月1日], [1月2日], [1月3日])
) AS PivotTable;
-- 動態 SQL 中格式化日期為字串作欄名
SELECT @sql = @sql + N', SUM(CASE CONVERT(VARCHAR(10), [日期], 120) WHEN ''' + CONVERT(VARCHAR(10), [日期], 120) + ''' THEN [數量] ELSE 0 END) AS [' + CONVERT(VARCHAR(10), [日期], 120) + ']'
FROM (SELECT DISTINCT CONVERT(VARCHAR(10), [日期], 120) AS Dt FROM EE) AS Dates;
動態 SQL 組裝 SUM(CASE...) 是 SQL Server 實作動態 PIVOT 的經典模式,靈活處理不固定欄名。SQL Server 2005+ 亦可使用 PIVOT 運算子 (靜態欄名)。選擇原則:欄名固定用 PIVOT 可讀性佳;欄名動態用動態 SQL。