1. 程式人生 > >Oracle 11g學習筆記--privot和unpivot子句

Oracle 11g學習筆記--privot和unpivot子句

Oracle 11g學習筆記–privot和unpivot子句

pivot子句是Oracle database 11g的新增特性,可以在查詢輸出中將行旋轉為列,同時對資料使用聚合函式。同時新增了unpivot子句,他可以在查詢輸出中將列旋轉為行;

引入

現在有以下表資料:

這裡寫圖片描述
(未顯示完全。。。)

現在我們想觀察(1, 2, 3)每種型別id在前四月的銷售情況;

你可能會這麼寫sql:

select  prd_type_id, month, sum(amount) 
from all_sales 
where month <= 4 and prd_type_id in
(1, 2, 3) group by month,prd_type_id order by prd_type_id;

這裡寫圖片描述

但是這種顯示結果也許並不清晰,想想如果把月份橫著排列是不是更清晰,若用一般方法我們可以這樣寫:

select 
    prd_type_id, 
    sum(decode(month, 1, amount, 0)) as JAN,
    sum(decode(month, 2, amount, 0)) as FEB,
    sum(decode(month, 3, amount, 0)) as MAR,
    sum(decode(month, 4, amount, 0
)) as APR from all_sales where prd_type_id in(1, 2, 3) group by prd_type_id;
--不熟悉decode函式的可以用一下方法 select prd_type_id, sum(case when month = 1 then amount else 0 end) as JAN, sum(case when month = 2 then amount else 0 end) as FEB, sum(case when month = 3 then amount else 0 end
) as MAR, sum(case when month = 4 then amount else 0 end) as APR from all_sales where prd_type_id in (1, 2, 3) group by prd_type_id;

這裡寫圖片描述

這樣顯示是不是更好呢?但是現在oracle 11g為我們提供了更好的方法, 那就是pivot,他可以將行變成列:

select *
from (
-- ①
    select month, prd_type_id, amount
    from all_sales
    where year = 2003
    and prd_type_id in(1, 2, 3)
)
pivot(
-- ②
    sum(amount) for month in (1 as JAN, 2 as FEB, 3 as MAR, 4 as APR)
)
order by prd_type_id;

執行結果同上圖;
接下來,我將講講這些程式碼的含義(只是個人理解):

對於①我的理解是,這部分限定了資料的範圍,這個範圍怎麼確定呢,首先你得知道你想顯示什麼。在本文中,你需要顯示prd_type_id, month, amount三種資料,所以就可以確定了;

對於②我的理解是,這部分規定了如何將行變成列;對於sum(amount)的含義,我們先放放,先說說這個month,他就規定了把什麼變成從行變成列了,那麼in後面的部分,則規定了,哪些month需要變成列,而as規定了別名,可以省略。那麼對於sum(amount)怎麼理解呢,首先他必須是聚合操作,他就是要在每一個month列下要顯示的資料,拿一月來說,他下面的資料肯定不止一條,這也是為什麼要使用聚合函式的原因了, 他到底對得是哪些amount的求和?我們知道在本題中,還有些列並未轉成行,那麼這些列同上面的月份便共同規定了對哪些amount求和了,如一月與id=1對應的那個格子,就是所有滿足月份為一月,而型別id為1的資料了;

轉換多個列

我們都知道for後面規定了哪些行將被轉換為列,而in裡面規定了要將哪些特定的行轉換,有了這些,我們便不能理解下面的sql:

select *
from (
    select month, prd_type_id, amount
    from all_sales
    where year = 2003 and prd_type_id in(1,2,3)
)
pivot (
    sum(amount) for(month, prd_type_id) in(
        (1, 1) as jan_prd_type_1,
        (2, 2) as feb_prd_type_2,
        (3, 3) as mar_prd_type_3,
        (4, 2) as apr_prd_type_2
    )
);

這裡寫圖片描述

在轉換中使用多個聚合函式

select  *
    from (
        select month, prd_type_id, amount
        from all_sales
        where year = 2003
        and prd_type_id in(1, 2, 3)
    )
    pivot (
        sum(amount) as sum_amount,
        avg(amount) as avg_amount
        for(month) in(
            1 as JAN, 2 as FEB
        )
    )
order by prd_type_id;

這裡寫圖片描述

值得注意的是系統會自動將兩個別名合為一個;

unpivot子句

unpivot子句的作用是將列轉換為行。

現有表格資料如下:
這裡寫圖片描述

select * from pivot_sales_data 
unpivot(
    amount for month in (jan, feb, mar, apr)
)
order by prd_type_id;

這裡寫圖片描述