Oracle分析函數

Oracle分析函數

本文講述Oracle分析函數用法,首先建庫:

Sql代碼  收藏代碼
  1. create table earnings -- 打工賺錢表  
  2. (  
  3.   earnmonth varchar2(6), -- 打工月份  
  4.   area varchar2(20), -- 打工地區  
  5.   sno varchar2(10), -- 打工者編號  
  6.   sname varchar2(20), -- 打工者姓名  
  7.   times int-- 本月打工次數  
  8.   singleincome number(10,2), -- 每次賺多少錢  
  9.   personincome number(10,2) -- 當月總收入  
  10. )  

然後插入實驗數據:

Sql代碼  收藏代碼
  1. insert into earnings values('200912','北平','511601','大魁',11,30,11*30);  
  2. insert into earnings values('200912','北平','511602','大凱',8,25,8*25);  
  3. insert into earnings values('200912','北平','511603','小東',30,6.25,30*6.25);  
  4. insert into earnings values('200912','北平','511604','大亮',16,8.25,16*8.25);  
  5. insert into earnings values('200912','北平','511605','賤敬',30,11,30*11);  
  6.   
  7. insert into earnings values('200912','金陵','511301','小玉',15,12.25,15*12.25);  
  8. insert into earnings values('200912','金陵','511302','小凡',27,16.67,27*16.67);  
  9. insert into earnings values('200912','金陵','511303','小妮',7,33.33,7*33.33);  
  10. insert into earnings values('200912','金陵','511304','小俐',0,18,0);  
  11. insert into earnings values('200912','金陵','511305','雪兒',11,9.88,11*9.88);  
  12.   
  13. insert into earnings values('201001','北平','511601','大魁',0,30,0);  
  14. insert into earnings values('201001','北平','511602','大凱',14,25,14*25);  
  15. insert into earnings values('201001','北平','511603','小東',19,6.25,19*6.25);  
  16. insert into earnings values('201001','北平','511604','大亮',7,8.25,7*8.25);  
  17. insert into earnings values('201001','北平','511605','賤敬',21,11,21*11);  
  18.   
  19. insert into earnings values('201001','金陵','511301','小玉',6,12.25,6*12.25);  
  20. insert into earnings values('201001','金陵','511302','小凡',17,16.67,17*16.67);  
  21. insert into earnings values('201001','金陵','511303','小妮',27,33.33,27*33.33);  
  22. insert into earnings values('201001','金陵','511304','小俐',16,18,16*18);  
  23. insert into earnings values('201001','金陵','511305','雪兒',11,9.88,11*9.88);  

然後看看剛剛建好的庫:

Sql代碼  收藏代碼
  1. select * from earnings;  

 

 

(1)sum函數,統計總合
按照月份,統計每個地區的總收入

Sql代碼  收藏代碼
  1. select earnmonth, area, sum(personincome)  
  2. from earnings  
  3. group by earnmonth,area;  

 查看結果如下:

 

(2)rollup函數
按照月份,地區統計收入

Sql代碼  收藏代碼
  1. select earnmonth, area, sum(personincome)  
  2. from earnings  
  3. group by rollup(earnmonth,area);  

 查看結果如下:

 

(3)cube函數
按照月份,地區進行收入總彙總

Sql代碼  收藏代碼
  1. select earnmonth, area, sum(personincome)  
  2. from earnings  
  3. group by cube(earnmonth,area)  
  4. order by earnmonth,area nulls last;  

 結果如下:

 

小結:sum是統計求和的函數。
group by 是分組函數,按照earnmonth和area先後次序分組。
以上三例都是先按照earnmonth分組,在earnmonth內部再按area分組,並在area組內統計personincome總合。
group by 後面什麼也不接就是直接分組。
group by 後面接 rollup 是在純粹的 group by 分組上再加上對earnmonth的彙總統計。
group by 後面接 cube 是對earnmonth彙總統計基礎上對area再統計。
另外那個 nulls last 是把空值放在最後。

rollup和cube區別:
如果是ROLLUP(A, B, C)的話,GROUP BY順序
(A、B、C)
(A、B)
(A)
最後對全表進行GROUP BY操作。

如果是GROUP BY CUBE(A, B, C),GROUP BY順序
(A、B、C)
(A、B)
(A、C)
(A),
(B、C)
(B)
(C),
最後對全表進行GROUP BY操作。

 

(4)grouping函數
在以上例子中,是用rollup和cube函數都會對結果集產生null,這時候可用grouping函數來確認
該記錄是由哪個字段得出來的
grouping函數用法,帶一個參數,參數爲字段名,結果是根據該字段得出來的就返回1,反之返回0

Sql代碼  收藏代碼
  1. select decode(grouping(earnmonth),1,'所有月份',earnmonth) 月份,  
  2.        decode(grouping(area),1,'全部地區',area) 地區, sum(personincome) 總金額  
  3. from earnings  
  4. group by cube(earnmonth,area)  
  5. order by earnmonth,area nulls last;  

 查看結果如下:

 

(5)rank() over開窗函數
按照月份、地區,求打工收入排序

Sql代碼  收藏代碼
  1. select earnmonth 月份,area 地區,sname 打工者, personincome 收入,   
  2.        rank() over (partition by earnmonth,area order by personincome desc) 排名  
  3. from earnings;  

 查看結果:

 

(6)dense_rank() over開窗函數
按照月份、地區,求打工收入排序2

Sql代碼  收藏代碼
  1. select earnmonth 月份,area 地區,sname 打工者, personincome 收入,   
  2.        dense_rank() over (partition by earnmonth,area order by personincome desc) 排名  
  3. from earnings;  

 結果如下:

 

(7)row_number() over開窗函數
按照月份、地區,求打工收入排序3

Sql代碼  收藏代碼
  1. select earnmonth 月份,area 地區,sname 打工者, personincome 收入,   
  2.        row_number() over (partition by earnmonth,area order by personincome desc) 排名  
  3. from earnings;  

 結果如下:

 

通過(5)(6)(7)發現rank,dense_rank,row_number的區別:
結果集中如果出現兩個相同的數據,那麼rank會進行跳躍式的排名,
比如兩個第二,那麼沒有第三接下來就是第四;
但是dense_rank不會跳躍式的排名,兩個第二接下來還是第三;
row_number最牛,即使兩個數據相同,排名也不一樣。

 

(8)sum累計求和
根據月份求出各個打工者收入總和,按照收入由少到多排序

Sql代碼  收藏代碼
  1. select earnmonth 月份,area 地區,sname 打工者,   
  2.        sum(personincome) over (partition by earnmonth,area order by personincome) 總收入  
  3. from earnings;  

 查看結果如下:

 

(9)max,min,avg和sum函數綜合運用
按照月份和地區求打工收入最高值,最低值,平均值和總額

Sql代碼  收藏代碼
  1. select distinct earnmonth 月份, area 地區,  
  2.        max(personincome) over(partition by earnmonth,area) 最高值,  
  3.        min(personincome) over(partition by earnmonth,area) 最低值,  
  4.        avg(personincome) over(partition by earnmonth,area) 平均值,  
  5.        sum(personincome) over(partition by earnmonth,area) 總額  
  6. from earnings;  

 結果如下:

 

(10)lag和lead函數
求出每個打工者上個月和下個月有沒有賺錢(personincome大於零即爲賺錢)

Sql代碼  收藏代碼
  1. select earnmonth 本月,sname 打工者,  
  2.        lag(decode(nvl(personincome,0),0,'沒賺','賺了'),1,0) over(partition by sname order by earnmonth) 上月,  
  3.        lead(decode(nvl(personincome,0),0,'沒賺','賺了'),1,0) over(partition by sname order by earnmonth) 下月  
  4. from earnings;  

 

 

說明:Lag和Lead函數可以在一次查詢中取出某個字段的前N行和後N行的數據(可以是其他字段的數據,比如根據字段甲查詢上一行或下兩行的字段乙),原來沒有分析函數的時候採用子查詢方法,但是比較麻煩,慚愧,我用子查詢有的還查不出來呢。

 

語法如下:

lag(value_expression [,offset] [,default]) over ([query_partition_clase] order_by_clause);
lead(value_expression [,offset] [,default]) over ([query_partition_clase] order_by_clause);
其中:
value_expression:可以是一個字段或一個內建函數。
offset是正整數,默認爲1,指往前或往後幾點記錄.因組內第一個條記錄沒有之前的行,最後一行沒有之後的行,
default就是用於處理這樣的信息,默認爲空。

 

再講講所謂的開窗函數,依本人遇見,開窗函數就是 over([query_partition_clase] order_by_clause)。比如說,我採用sum求和,rank排序等等,但是我根據什麼來呢?over提供一個窗口,可以根據什麼什麼分組,就用partition by,然後在組內根據什麼什麼進行內部排序,就用 order by。

 

這就是我理解的開窗函數。好了本文先寫到這,以後再有什麼心得體會再來補充。

【轉自 http://love-flying-snow.iteye.com/blog/573083

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