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


總結,基本上按照語法套用即可,注意將源表非相關列先過濾掉,可是是子查詢,也可以是視圖。 
--------------------- 
作者:Seandba 
來源:CSDN 
原文:https://blog.csdn.net/seandba/article/details/72730657?utm_source=copy 
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM