函數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 版權聲明:本文為博主原創文章,轉載請附上博文鏈接!
