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函數用法,帶一個參數,參數為字段名,如果當前行是由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。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM