rollup 通常和group by语句一起使用,是根据维度在分组的结果集中进行聚合操作(通常为汇总,这取决于SELECT后的聚合函数)。最常用的场景是:为每个分组返回一个小计,同时为所有分组返回总计。
1、不带rollup的goup by :
Group by A ,B产生的分组种数:1种;
返回结果集:也就是这一种分组的结果集。
2、带rollup但group by与rollup之间没有任何内容:
1)Group by rollup(A ,B) 产生的分组种数:3种;
返回结果集:为以上三种分组统计结果集的并集且未去掉重复数据。
2)Group by rollup(A ,B,C) 产生的分组种数:4种;
第四种:group by NULL
返回结果集:为以上四种分组统计结果集的并集且未去掉重复数据。
3、带rollup但group by与rollup之间还包含有列信息 :
1)Group by A , rollup(A ,B) 产生的分组种数:3种;
返回结果集:为以上三种分组统计结果集的并集且未去掉重复数据。
2)Group by C , rollup(A ,B) 产生的分组种数:3种;
返回结果集:为以上三种分组统计结果集的并集且未去掉重复数据。
4、带rollup且rollup子句括号内又使用括号对列进行组合:
1)Group by rollup((A ,B)) 产生的分组种数:2种;
返回结果集:为以上两种分组统计结果集的并集且未去掉重复数据。
2)Group by rollup(A ,(B,C)) 产生的分组种数:3种;
返回结果集:为以上三种分组统计结果集的并集且未去掉重复数据。
对这种情况,可以理解为几个列被括号括在一起时,就只能被看成一个整体,分组时不需要再细化。因此也可推断rollup括号内也顶多加到一重括号,加多重了应该没有任何意义(这个推断我没有做验证的哦)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | SQL> select ename,deptno,sum(sal) from emp group by rollup(deptno,ename); ENAME DEPTNO SUM(SAL) ---------- ---------- ---------- KING 10 5000 CLARK 10 2450 MILLER 10 1300 10 8750 FORD 20 3000 ADAMS 20 1100 JONES 20 2975 SCOTT 20 3000 SMITH 20 800 20 10875 WARD 30 1250 ENAME DEPTNO SUM(SAL) ---------- ---------- ---------- ALLEN 30 1600 BLAKE 30 2850 JAMES 30 950 MARTIN 30 1250 TURNER 30 1500 30 9400 29025 |
1 2 3 4 5 | select decode(grouping(f_line)+grouping(f_workarea),1,'小计',2,'总计',f_workarea) f_workarea, decode(grouping(f_line),1,count(*)||'条',f_line) f_line, sum(f_pagesnumber) sum_pagesnumbers from t_testcount group by rollup (f_workarea,f_line); |
grouping()函数:
必须接受一列且只能接受一列做为其参数。参数列值为空返回1,参数列值非空返回0。(如果参数的列在rollup中,则返回1;否则返回0)
grouping_id()函数:
必须接受一列或多列做为其参数。返回值为按参数排列顺序,依次对各个参数使用grouping()函数,并将结果值依次串成一串二进制数然后再转化为十进制所得到的值。
例如:grouping(A) = 0 ; grouping(B) = 1;
则:grouping_id(A,B) = (01)2 = 1;
grouping_id(B,A) = (10)2 =2;
group_id()函数
调用时不需要且不能传入任何参数。返回值为某个特定的分组出现的重复次数(第一大点中的第3种情况中往往会产生重复的分组)。重复次数从0开始,例如某个分组第一次出现则返回值为0,第二次出现时返回值为1,……,第n次出现返回值为n-1。
注:使用以上三个函数往往是为了过滤掉一部分统计数据,而达到美化统计结果的作用。
rollup是cube的一种特殊情况,和rollup一样,cube也是根据维度在分组的结果集中进行聚合操作。但是rollup只在层次上对数据进行聚合,而cube对所有的维度进行聚合。具有N个维度的列,cube需要2的N次方次分组操作,而rollup只需要N次分组操作。
带cube子句的group by会产生更多的分组统计数据。cube后的列有多少种组合(注意组合是与顺序无关的)就会有多少种分组。
假设有n个维度,rollup会有n个聚合:
rollup(a,b) 统计列包含:(a,b)、(a)、()
rollup(a,b,c) 统计列包含:(a,b,c)、(a,b)、(a)、()
……以此类推ing……
假设有n个纬度,cube会有2的n次方个聚合:
cube(a,b) 统计列包含:(a,b)、(a)、(b)、()
cube(a,b,c) 统计列包含:(a,b,c)、(a,b)、(a,c)、(b,c)、(a)、(b)、(c)、()
……以此类推ing……
oracle中,允许在group by后面使用 grouping sets(…) 语句。通过该语句可以实现rollup、cube同样的功能。
返回结果集:为以上两种分组统计结果集的并集且未去掉重复数据。
返回结果集:为以上二种分组统计结果集的并集且未去掉重复数据。
- SQL> select deptno,job,sum(sal) from emp group by deptno,job order by deptno;
- 2 单独使用分组查询
- 3
- 4 DEPTNO JOB SUM(SAL)
- 5 ------ --------- ----------
- 6 10 CLERK 1300
- 7 10 MANAGER 2450
- 8 10 PRESIDENT 5000
- 9 20 ANALYST 6000
- 10 20 CLERK 1900
- 11 20 MANAGER 2975
- 12 30 CLERK 950
- 13 30 MANAGER 2850
- 14 30 SALESMAN 5600
- 15
- 16 已选择9行。
-
- 使用rollup函数分组:
- SQL> select deptno,job,sum(sal) from emp group by rollup(deptno,job) order by deptno;
- 19
- 20 DEPTNO JOB SUM(SAL)
- 21 ------ --------- ----------
- 22 10 CLERK 1300 第一次分组的sum总和计算
- 23 10 MANAGER 2450
- 24 10 PRESIDENT 5000
- 25 10 8750 第二次分组添加的计算(分组小计)
- 26 20 ANALYST 6000
- 27 20 CLERK 1900
- 28 20 MANAGER 2975
- 29 20 10875
- 30 30 CLERK 950
- 31 30 MANAGER 2850
- 32 30 SALESMAN 5600
- 33 30 9400
- 34 29025 第三次分组添加的计算(总计)
- 35 所以rollup函数进行多次分组计算
- 36
- 37 已选择13行。