SQL 中提供了好用的 PIVOT 語法,可以用來旋轉表格,進行彙總作業。
PIVOT 語法說明
SELECT 非 PIVOT 欄位
, 第一個 PIVOT 欄位
, 第二個 PIVOT 欄位
...
, 最後的 PIVOT 欄位
FROM
資料來源
PIVOT
(
要使用的彙總函數(被彙總欄位)
FOR
包含 PIVOT 類別的欄位
IN (第一個 PIVOT 欄位, 第二個 PIVOT 欄位, ... , 最後的 PIVOT 欄位)
) AS PIVOT 表格別名
選擇性的 ORDER BY 子句;
範例
CREATE TABLE Customer(
[Name] VARCHAR(20),
ItemClass VARCHAR(20),
ItemPrice MONEY
)
INSERT INTO Customer ([Name], ItemClass, ItemPrice)
VALUES ('小明' , '玩具', '100'), ('小華', '書籍', '200')
, ('小美', '書籍', '150'), ('小華', '書籍', '200')
, ('小明', '零食', '75'), ('小華', '零食', '120');
SELECT [Name], ItemClass, ItemPrice FROM Customer
SELECT PVT.Name
, ISNULL(PVT.玩具, 0) AS 玩具
, ISNULL(PVT.書籍, 0) AS 書籍
, ISNULL(PVT.零食, 0) AS 零食
FROM Customer
PIVOT(
SUM (ItemPrice)
FOR ItemClass IN ([玩具], [書籍], [零食])
) AS PVT
DROP TABLE Customer
原本的資料表為:
Name | ItemClass | ItemPrice |
---|---|---|
小明 | 玩具 | 100.00 |
小華 | 書籍 | 200.00 |
小美 | 書籍 | 150.00 |
小華 | 書籍 | 200.00 |
小明 | 零食 | 75.00 |
小華 | 零食 | 120.00 |
用 PIVOT 旋轉後會變成:
Name | 玩具 | 書籍 | 零食 |
---|---|---|---|
小明 | 100.00 | 0.00 | 75.00 |
小美 | 0.00 | 150.00 | 0.00 |
小華 | 0.00 | 400.00 | 120.00 |
ISNULL 函數可以參考拙作:SQL 避免除以 0 的錯誤 - ISNULL 和 NULLIF 函數
注意
如果在 SQL 中以 PIVOT 旋轉並彙總部分相同的資料,有可能會造成「原始相同的資料」計算結果錯誤。例如以下的範例:SQL Server PIVOT returns only one row - Database Administrators Stack Exchange
這時可以為資料用 ROW_NUMBER
函數建立編號,使其被視為不同的資料,再呼叫 PIVOT 旋轉。(關於此函數的解說,請參考拙作:SQL 用 ROW_NUMBER 和其它次序函數產生名次)
(我曾遇過計算金額時,在使用 PIVOT 旋轉並彙總某一欄位之後,又再次用 PIVOT 彙總資料中另一個欄位,由於「PIVOT 後完全相同的資料只會留下一筆」,因此可能造成「同一人員的相同金額」計算錯誤。)