[转]详解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

相关文章
相关标签/搜索