本文主要讲解 ROLLUP, CUBE, GROUPING SETS的主要用法,这些函数能够理解为GroupBy分组函数封装后的精简用法,至关于多个union all 的组合显示效果,可是要比 多个union all的效率要高。oracle
其实这些函数在时间的程序开发中应用的并很少,至少在我工做的多年时间中没用过几回,由于如今的各类开发工具/平台都自带了这些高级分组统计功能,使用的方便性及美观性都比这些要好。但若是临时查下数据,用这些函数仍是不错的。函数
建立测试环境
1. 建立表工具
- createtable EMP2
- (
- ID NUMBER,
- NAME VARCHAR2(20),
- SEX VARCHAR2(2),
- HIREDATE DATE,
- BASE VARCHAR2(20),
- DEPT VARCHAR2(20),
- SAL NUMBER
- );
2. 插入测试数据post
- insert into emp2 (ID, NAME, SEX, HIREDATE,BASE, DEPT, SAL)
- values (107, '小月', '女', to_date('01-09-2013', 'dd-mm-yyyy'), '北京','营运', 9000);
- insert into emp2 (ID, NAME, SEX, HIREDATE,BASE, DEPT, SAL)
- values (108, '小美', '女', to_date('01-06-2011', 'dd-mm-yyyy'), '上海','营运', 11000);
- insert into emp2 (ID, NAME, SEX, HIREDATE,BASE, DEPT, SAL)
- values (101, '张三', '男', to_date('01-01-2011', 'dd-mm-yyyy'), '北京','财务', 8000);
- insert into emp2 (ID, NAME, SEX, HIREDATE,BASE, DEPT, SAL)
- values (102, '李四', '男', to_date('01-01-2012', 'dd-mm-yyyy'), '北京','营运', 15000);
- insert into emp2 (ID, NAME, SEX, HIREDATE,BASE, DEPT, SAL)
- values (103, '王五', '男', to_date('01-01-2013', 'dd-mm-yyyy'), '上海','营运', 6000);
- insert into emp2 (ID, NAME, SEX, HIREDATE,BASE, DEPT, SAL)
- values (104, '赵六', '男', to_date('01-01-2014', 'dd-mm-yyyy'), '上海','财务', 10000);
- insert into emp2 (ID, NAME, SEX, HIREDATE,BASE, DEPT, SAL)
- values (105, '小花', '女', to_date('01-08-2014', 'dd-mm-yyyy'), '上海','财务', 4000);
- insert into emp2 (ID, NAME, SEX, HIREDATE,BASE, DEPT, SAL)
- values (106, '小静', '女', to_date('01-01-2015', 'dd-mm-yyyy'), '北京','财务', 6000);
- commit;
3. 查看一下刚才插入的数据开发工具
4. 先看下普通分组的效果测试
按照地区统计每一个部门的总工资spa
- select base,dept ,sum(sal) from emp2
- 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操做
按照地区统计每一个部门的总工资,按工做母地汇总,再合计
- select base,dept,sum(sal) from emp2
- groupbyrollup(base,dept);

结果至关于
- select base,dept,sum(sal) from emp2
- group by base,dept
- unionall
- select base,null,sum(sal) from emp2
- group by base,null
- unionall
- selectnull,null,sum(sal) from emp2
- group by null,null
- order by 1,2
若是颠倒下rollup顺序则结果以下:
- select base,dept,sum(sal) from emp2
- group by rollup(dept,base);

若是在实际查询中,有的小计或合计咱们不须要,那么就要使用局部rollup,局部rollup就是将须要固定统计的列放在group by中,而不是放在rollup中。
- select base,dept,sum(sal) from emp2
- group by dept,rollup(base);

与group by rollup(dept,base)相比:去掉了最后一行的汇总,由于每次汇总要么是dept,base,要么是dept,null ,dept是固定的。
若是只但愿看到合计则能够这样写:
- select base,dept ,sum(sal) from emp2
- group by rollup((base,dept));

CUBE(交叉列表)
CUBE也是对group by运算的一种扩展,它比rollup扩展更加精细,组合类型更多,rollup是按组合的列从右到左递减分组计算,而CUBE则是对全部可能的组合状况进行分组,这样分组的状况更多,覆盖全部的可能分组,并计算全部可能的分组的小计。
对于CUBE来讲,列的名字只要同样,那么顺序无所谓,结果都是同样的,由于cube是各类可能状况的组合,只不过统计的结果顺序不一样而已。可是对于rollup来讲,列的顺序不一样,则结果不一样。
好比对工做母地和部门的交叉统计
- select base,dept,sum(sal) from emp2
- group by cube(base,dept)
- order by 1,2;

部分CUBE和部分ROLLUP相似,把须要固定统计的列放到group by中,不放到cube中就能够了。
若是cube中只有一个列,那么和rollup的结果一致
- select base,dept,sum(sal) from emp2
- group by dept,cube(base)
- 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中。
好比须要分别统计工做母地与部门的合计:
- select base,dept,sum(sal) from emp2
- group by grouping sets(base,dept);
结果为:

等价于
- select base,null,sum(sal) from emp2
- group by base,null
- unionall
- select null,dept,sum(sal) from emp2
- group by null,dept;
理解了groupingsets的原理咱们用他实现rollup的功能也是能够的:
- select base,dept,sum(sal) from emp2
- group by grouping sets ((base,dept),dept,null);
效果以下:

grouping函数
在以上例子中,是用rollup和cube函数都会对结果集产生null,这时候可用grouping函数来确认该记录是由哪一个字段得出来的
grouping函数用法,带一个参数,参数为字段名,结果是根据该字段得出来的就返回1,反之返回0
例如:
- select decode(grouping(base),1,'全部地区',base) base,
- decode(grouping(dept),1,'全部部门',dept)dept ,sum(sal) from emp2
- 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