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;

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章