1. 程式人生 > >Oracle SQL函式pivot、unpivot轉置函式實現行轉列、列轉行

Oracle SQL函式pivot、unpivot轉置函式實現行轉列、列轉行

函式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