原文地址:http://blog.csdn.net/seandba/article/details/72730657
函數PIVOT、UNPIVOT轉置函數實現行轉列、列轉行,效果如下圖所示:
1.PIVOT為行轉列,從圖示的左邊到右邊
2.UNPIVOT為列轉行,從圖示的右邊到左邊
3.左邊為縱表,結構簡單,易擴展
4.右邊為橫表,展示清晰,方便查詢
5.很多時候業務表為縱表,但是統計分析需要的結果如右邊的橫表,這時候就需要用到轉置函數了
示例圖表:

Pivot語法:
- SELECT ....
- FROM <table-expr>
- PIVOT
- (
- aggregate-function(<column>)
- FOR <pivot-column> IN (<value1>, <value2>,..., <valuen>)
- ) AS <alias>
- WHERE .....
注意:
- FOR <pivot-column>
這個是不支持表達式的,如果需要,請通過子查詢或者視圖先預處理。
Pivot
例子1:先構造一個子查詢,然后根據CHANNEL列進行轉置,源表sales_view里面可能有很多列,不需要列先通過子查詢過濾掉再進行轉置。
另外轉置后的列指定了別名,值是對amount_sold列的匯總。
- SELECT * FROM
- (SELECT product, channel, amount_sold
- FROM sales_view
- ) S PIVOT (SUM(amount_sold)
- FOR CHANNEL IN (3 AS DIRECT_SALES, 4 AS INTERNET_SALES,
- 5 AS CATALOG_SALES, 9 AS TELESALES))
- ORDER BY product;
- PRODUCT DIRECT_SALES INTERNET_SALES CATALOG_SALES TELESALES
- ---------------------- ------------ -------------- ------------- ---------
- ...
- Internal 6X CD-ROM 229512.97 26249.55
- Internal 8X CD-ROM 286291.49 42809.44
- Keyboard Wrist Rest 200959.84 38695.36 1522.73
- ...
例子2:基於多列進行轉置,下面例子是基於channel、quarter兩列進行轉置
- SELECT *
- FROM
- (SELECT product, channel, quarter, quantity_sold
- FROM sales_view
- ) PIVOT (SUM(quantity_sold)
- FOR (channel, quarter) IN
- ((5, '02') AS CATALOG_Q2,
- (4, '01') AS INTERNET_Q1,
- (4, '04') AS INTERNET_Q4,
- (2, '02') AS PARTNERS_Q2,
- (9, '03') AS TELE_Q3
- )
- );
- PRODUCT CATALOG_Q2 INTERNET_Q1 INTERNET_Q4 PARTNERS_Q2 TELE_Q3
- ------- ---------- ----------- ----------- ----------- -------
- ...
- Bounce 347 632 954
- ...
- Smash Up Boxing 129 280 560
- ...
- Comic Book Heroes 47 155 275
- ...
例子3:對多列的值進行匯總計算,以下是基於channel例進行轉置,然后對amount_sold和quantity_sold兩列進行合計運算
- SELECT *
- FROM
- (SELECT product, channel, amount_sold, quantity_sold
- FROM sales_view
- ) PIVOT (SUM(amount_sold) AS sums,
- SUM(quantity_sold) AS sumq
- FOR channel IN (5, 4, 2, 9)
- )
- ORDER BY product;
- PRODUCT 5_SUMS 5_SUMQ 4_SUMS 4_SUMQ 2_SUMS 2_SUMQ 9_SUMS 9_SUMQ
- ------------- ------ ------ ------ ------ ------ ------ ------ ------
- O/S Doc Set English 142780.36 3081 381397.99 8044 6028.66 134
- O/S Doc Set French 55503.58 1192 132000.77 2782
- ...
Unpivot
unpivot是pivot的相反操作,進行的是列轉行
例子1:先看源表結構,for子句指定將(Q1_SUMQ, Q2_SUMQ, Q3_SUMQ, Q4_SUMQ)這4列轉置為行,
for子句之前的quantity_sold是4列轉置后的列名,
decode還定義了每列轉置為行后新標示列的值,這個等下看第2個例子可以看到,也可以在 in 子句后面加 as 指定別名。
UNPIVOT INCLUDE NULLS 指定空值也進行轉置,如果是EXCLUDE NULLS 將忽略空值。
- SELECT *
- FROM pivotedTable
- ORDER BY product;
- PRODUCT Q1_SUMQ Q1_SUMA Q2_SUMQ Q2_SUMA Q3_SUMQ Q3_SUMA Q4_SUMQ Q4_SUMA
- --------------- ------- ------- ------- -------- ------- -------- ------- ---------
- 1.44MB External 6098 58301.33 5112 49001.56 6050 56974.3 5848 55341.28
- 128MB Memory 1963 110763.63 2361 132123.12 3069 170710.4 2832 157736.6
- 17" LCD 1492 1812786.94 1387 1672389.06 1591 1859987.66 1540 1844008.11
- SELECT product, DECODE(quarter, 'Q1_SUMQ', 'Q1', 'Q2_SUMQ', 'Q2', 'Q3_SUMQ', 'Q3',
- 'Q4_SUMQ', 'Q4') AS quarter, quantity_sold
- FROM pivotedTable
- UNPIVOT INCLUDE NULLS
- (quantity_sold
- FOR quarter IN (Q1_SUMQ, Q2_SUMQ, Q3_SUMQ, Q4_SUMQ))
- ORDER BY product, quarter;
- PRODUCT QUARTER QUANTITY_SOLD
- ------- -- -------------
- 1.44MB External 3.5" Diskette Q1 6098
- 1.44MB External 3.5" Diskette Q2 5112
- 1.44MB External 3.5" Diskette Q3 6050
- 1.44MB External 3.5" Diskette Q4 5848
- 128MB Memory Card Q1 1963
- 128MB Memory Card Q2 2361
- 128MB Memory Card Q3 3069
- 128MB Memory Card Q4 2832
- ...
例子2:轉置多列的情況
- SELECT product, quarter, quantity_sold, amount_sold
- FROM pivotedTable
- UNPIVOT INCLUDE NULLS
- (
- (quantity_sold, amount_sold)
- FOR quarter IN ((Q1_SUMQ, Q1_SUMA) AS 'Q1', (Q2_SUMQ, Q2_SUMA) AS 'Q2', (Q3_SUMQ, Q3_SUMA) AS 'Q3', (Q4_SUMQ, Q4_SUMA) AS 'Q4'))
- ORDER BY product, quarter;
- PRODUCT QU QUANTITY_SOLD AMOUNT_SOLD
- ----------------------------- -- ------------- ------------
- 1.44MB External 3.5" Diskette Q1 6098 58301.33
- 1.44MB External 3.5" Diskette Q2 5112 49001.56
- 1.44MB External 3.5" Diskette Q3 6050 56974.3
- 1.44MB External 3.5" Diskette Q4 5848 55341.28
- 128MB Memory Card Q1 1963 110763.63
- 128MB Memory Card Q2 2361 132123.12
- 128MB Memory Card Q3 3069 170710.4
- 128MB Memory Card Q4 2832 157736.6
總結,基本上按照語法套用即可,注意將源表非相關列先過濾掉,可是是子查詢,也可以是視圖。
最后試試解決這個問題吧,看你是否真的懂了!
http://blog.csdn.net/seandba/article/details/72629724
以上內容均來自Oracle11g官方文檔,我只是搬運工。。。
Oracle® Database Data Warehousing Guide
11g Release 2 (11.2)
E25554-01
