將「縱表」(長格式)轉為「橫表」(寬格式),或反之,常用於報表呈現、資料匯入匯出、ETL 轉換。


SELECT
Name,
SUM(CASE WHEN Course = N'語文' THEN Grade ELSE 0 END) AS Chinese,
SUM(CASE WHEN Course = N'數學' THEN Grade ELSE 0 END) AS Mathematics,
SUM(CASE WHEN Course = N'英語' THEN Grade ELSE 0 END) AS English
FROM dbo.Table_A
GROUP BY Name;
SELECT Name, [語文] AS Chinese, [數學] AS Mathematics, [英語] AS English
FROM (
SELECT Name, Course, Grade FROM Table_A
) AS SourceTable
PIVOT (
SUM(Grade) FOR Course IN ([語文], [數學], [英語])
) AS PivotTable;


SELECT Name, 'Chinese' AS Course, Chinese AS Score FROM Table_B UNION ALL SELECT Name, 'Mathematics' AS Course, Mathematics AS Score FROM Table_B UNION ALL SELECT Name, 'English' AS Course, English AS Score FROM Table_B ORDER BY Name, Course DESC;
SELECT Name, Course, Score
FROM Table_B
UNPIVOT (
Score FOR Course IN (Chinese, Mathematics, English)
) AS UnpivotTable;
| 方法 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|
| CASE + GROUP BY | 相容所有版本、可控邏輯複雜度 | 手動列舉欄位 | 固定欄位、複雜轉換邏輯 |
| PIVOT/UNPIVOT | 語法簡潔、標準化 | 動態欄位需動態 SQL | 固定欄位、標準報表 |
| UNION ALL | 效能最佳、無排序開銷 | 程式碼重複 | 大量資料、高頻轉換 |
若欄位不固定(如不確定科目),需構建動態 SQL:
DECLARE @cols NVARCHAR(MAX), @sql NVARCHAR(MAX);
SELECT @cols = STRING_AGG(QUOTENAME(Course), ',') FROM (SELECT DISTINCT Course FROM Table_A) t;
SET @sql = 'SELECT Name, ' + @cols + ' FROM Table_A PIVOT (SUM(Grade) FOR Course IN (' + @cols + ')) p';
EXEC sp_executesql @sql;
縱橫轉換核心在於聚合邏輯與欄位展開。固定結構優先用 PIVOT/UNPIVOT 或 CASE 聚合;動態結構需動態 SQL;大數據量選 UNION ALL 避免排序開銷。