ORACLE統計分析函數

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

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. )  
 

而後插入實驗數據:express

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函數,統計總合
按照月份,統計每個地區的總收入spa

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

 查看結果以下:code

 

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

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

 查看結果以下:string

 

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

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

 結果以下:io

 

小結: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操做。table

 

(4)grouping函數
在以上例子中,是用rollup和cube函數都會對結果集產生null,這時候可用grouping函數來確認
該記錄是由哪一個字段得出來的
grouping函數用法,帶一個參數,參數爲字段名,若是當前行是由rollup或者cube彙總得來的,結果就返回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代碼   收藏代碼
   select earnmonth 月份,area 地區,sname 打工者, personincome 收入,     
    row_number() over (partition  by earnmonth,area order by personincome desc) 排名 
    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。

相關文章
相關標籤/搜索