[轉]詳解Oracle高級分組函數(ROLLUP, CUBE, GROUPING SETS)

原文地址:http://blog.csdn.net/u014558001/article/details/42387929sql

本文主要講解 ROLLUP, CUBE, GROUPING SETS的主要用法,這些函數能夠理解爲GroupBy分組函數封裝後的精簡用法,至關於多個union all 的組合顯示效果,可是要比 多個union all的效率要高。oracle

其實這些函數在時間的程序開發中應用的並很少,至少在我工做的多年時間中沒用過幾回,由於如今的各類開發工具/平臺都自帶了這些高級分組統計功能,使用的方便性及美觀性都比這些要好。但若是臨時查下數據,用這些函數仍是不錯的。函數

建立測試環境

1.      建立表工具

 

  1. createtable EMP2  
  2. (  
  3.   ID       NUMBER,  -- 員工編號  
  4.   NAME     VARCHAR2(20), --姓名  
  5.   SEX     VARCHAR2(2),  --性別  
  6.   HIREDATE DATE,         --入職日期  
  7.   BASE    VARCHAR2(20), --工做母地  
  8.   DEPT    VARCHAR2(20), --所在部門  
  9.   SAL     NUMBER        --月工資  
  10. );  

 

2.      插入測試數據post

 

  1. insert into emp2 (ID, NAME, SEX, HIREDATE,BASE, DEPT, SAL)  
  2. values (107, '小月', '女', to_date('01-09-2013', 'dd-mm-yyyy'), '北京','營運', 9000);  
  3. insert into emp2 (ID, NAME, SEX, HIREDATE,BASE, DEPT, SAL)  
  4. values (108, '小美', '女', to_date('01-06-2011', 'dd-mm-yyyy'), '上海','營運', 11000);  
  5. insert into emp2 (ID, NAME, SEX, HIREDATE,BASE, DEPT, SAL)  
  6. values (101, '張三', '男', to_date('01-01-2011', 'dd-mm-yyyy'), '北京','財務', 8000);  
  7. insert into emp2 (ID, NAME, SEX, HIREDATE,BASE, DEPT, SAL)  
  8. values (102, '李四', '男', to_date('01-01-2012', 'dd-mm-yyyy'), '北京','營運', 15000);  
  9. insert into emp2 (ID, NAME, SEX, HIREDATE,BASE, DEPT, SAL)  
  10. values (103, '王五', '男', to_date('01-01-2013', 'dd-mm-yyyy'), '上海','營運', 6000);  
  11. insert into emp2 (ID, NAME, SEX, HIREDATE,BASE, DEPT, SAL)  
  12. values (104, '趙六', '男', to_date('01-01-2014', 'dd-mm-yyyy'), '上海','財務', 10000);  
  13. insert into emp2 (ID, NAME, SEX, HIREDATE,BASE, DEPT, SAL)  
  14. values (105, '小花', '女', to_date('01-08-2014', 'dd-mm-yyyy'), '上海','財務', 4000);  
  15. insert into emp2 (ID, NAME, SEX, HIREDATE,BASE, DEPT, SAL)  
  16. values (106, '小靜', '女', to_date('01-01-2015', 'dd-mm-yyyy'), '北京','財務', 6000);  
  17. commit;  

 

 

3.     查看一下剛纔插入的數據開發工具

 

  1. select * from emp2;  

 

 

 

4.      先看下普通分組的效果測試

按照地區統計每一個部門的總工資spa

  1. select base,dept ,sum(sal) from emp2   
  2. group by base,dept;  

查看結果以下:.net

 

 

ROLLUP(累計累加)

ROLLUP是對group by的擴展,所以,它只能出如今group by子句中,依賴於分組的列,對每一個分組會生成彙總數據, rollup和group by聯合一塊兒使用,達到了按group by列順序分組,而且實現小計和合計的功能。rollup分組仍是有序的,先所有分組,而後對每一個分組小計,最後合計。code

rollup中列的順序不一樣,則統計的結果不一樣。由於它是按列從右遞減分組的。

好比 Group by  ROLLUP(A, B, C),首先會對(A、B、C)進行GROUP BY,而後對(A、B)進行GROUP BY,而後是(A)進行GROUP BY,最後對全表進行GROUP BY操做

 

按照地區統計每一個部門的總工資,按工做母地彙總,再合計

 

  1. select base,dept,sum(sal) from emp2   
  2. groupbyrollup(base,dept);  

 

 

 

結果至關於

 

  1. select base,dept,sum(sal) from emp2   
  2. group by base,dept  
  3. unionall  
  4. select base,null,sum(sal) from emp2   
  5. group by base,null  
  6. unionall  
  7. selectnull,null,sum(sal) from emp2   
  8. group by null,null  
  9. order by 1,2  

 

 

 

若是顛倒下rollup順序則結果以下:

  1. select base,dept,sum(sal) from emp2   
  2. group by rollup(dept,base);  

 

 

若是在實際查詢中,有的小計或合計咱們不須要,那麼就要使用局部rollup,局部rollup就是將須要固定統計的列放在group by中,而不是放在rollup中。

 

 

  1. select base,dept,sum(sal) from emp2   
  2. group by dept,rollup(base);  


 

與group by rollup(dept,base)相比:去掉了最後一行的彙總,由於每次彙總要麼是dept,base,要麼是dept,null ,dept是固定的。

 

 

若是隻但願看到合計則能夠這樣寫:

 

  1. select base,dept ,sum(sal) from emp2   
  2. group by rollup((base,dept));  

 

 

 

 

 

CUBE(交叉列表)

CUBE也是對group by運算的一種擴展,它比rollup擴展更加精細,組合類型更多,rollup是按組合的列從右到左遞減分組計算,而CUBE則是對全部可能的組合狀況進行分組,這樣分組的狀況更多,覆蓋全部的可能分組,並計算全部可能的分組的小計。

 

對於CUBE來講,列的名字只要同樣,那麼順序無所謂,結果都是同樣的,由於cube是各類可能狀況的組合,只不過統計的結果順序不一樣而已。可是對於rollup來講,列的順序不一樣,則結果不一樣。

 

 

好比對工做母地和部門的交叉統計

  1. select base,dept,sum(sal) from emp2   
  2. group by cube(base,dept)  
  3. order by 1,2;  

 

 

 

部分CUBE和部分ROLLUP相似,把須要固定統計的列放到group by中,不放到cube中就能夠了。

若是cube中只有一個列,那麼和rollup的結果一致

 

 

  1. select base,dept,sum(sal) from emp2   
  2. group by dept,cube(base)  
  3. order by1,2;  

 

 

 

rollup和cube區別:

若是是ROLLUP(A,B, C)的話,GROUP BY順序

(A、B、C)

(A、B)

(A)

最後對全表進行GROUPBY操做。

若是是GROUP BY CUBE(A, B, C),GROUP BY順序
(A、B、C)

(A、B)

(A、C)

(A),

(B、C)

(B)

(C),

最後對全表進行GROUPBY操做。

 

GROUPING SETS

對group by的另外一個擴展,專門對分組列分別進行小計計算,不包括合計。使用方式和rollup和cube同樣,都是放在group by中。

  

好比須要分別統計工做母地與部門的合計:

 

  1. select base,dept,sum(sal) from emp2   
  2. group by grouping sets(base,dept);  

結果爲:

 

等價於

 

  1. select base,null,sum(sal) from emp2   
  2. group by  base,null  
  3. unionall  
  4. select null,dept,sum(sal) from emp2   
  5. group by  null,dept;  

 

 

理解了groupingsets的原理咱們用他實現rollup的功能也是能夠的:

 

  1. select base,dept,sum(sal) from emp2   
  2. group by grouping sets ((base,dept),dept,null);  

 

效果以下:

 

 

 

 

grouping函數

在以上例子中,是用rollup和cube函數都會對結果集產生null,這時候可用grouping函數來確認該記錄是由哪一個字段得出來的

grouping函數用法,帶一個參數,參數爲字段名,結果是根據該字段得出來的就返回1,反之返回0

例如:

 

  1. select decode(grouping(base),1,'全部地區',base) base,  
  2. decode(grouping(dept),1,'全部部門',dept)dept ,sum(sal) from emp2   
  3. group by rollup(dept,base);  

 

 

 

 

更多ROLLUP,CUBE, GROUPING SETS與GROUP BY的關係能夠參考Oracle官方文檔中的例子

 

http://docs.oracle.com/cd/E11882_01/server.112/e25554/aggreg.htm#DWHSG8608

相關文章
相關標籤/搜索