用 SQL 的 PIVOT 語法旋轉資料

March 15, 2023

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 後完全相同的資料只會留下一筆」,因此可能造成「同一人員的相同金額」計算錯誤。)