rollup和grouping函数
Posted sunshineicy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了rollup和grouping函数相关的知识,希望对你有一定的参考价值。
转载:http://blog.itpub.net/519536/viewspace-610995/
本文通过演示给出Oracle ROLLUP分组函数的用法,体验一下Oracle在统计查询领域中的函数魅力。ROLLUP分组函数可以理解为Group By分组函数封装后的精简用法,这里同时给出ROLLUP的Group By的改写思路。
1.初始化实验坏境
1)创建测试表group_test
SECOOLER@ora11g> create table group_test (group_id int, job varchar2(10), name varchar2(10), salary int);
Table created.
2)初始化数据
insert into group_test values (10,\'Coding\', \'Bruce\',1000);
insert into group_test values (10,\'Programmer\',\'Clair\',1000);
insert into group_test values (10,\'Architect\', \'Gideon\',1000);
insert into group_test values (10,\'Director\', \'Hill\',1000);
insert into group_test values (20,\'Coding\', \'Jason\',2000);
insert into group_test values (20,\'Programmer\',\'Joey\',2000);
insert into group_test values (20,\'Architect\', \'Martin\',2000);
insert into group_test values (20,\'Director\', \'Michael\',2000);
insert into group_test values (30,\'Coding\', \'Rebecca\',3000);
insert into group_test values (30,\'Programmer\',\'Rex\',3000);
insert into group_test values (30,\'Architect\', \'Richard\',3000);
insert into group_test values (30,\'Director\', \'Sabrina\',3000);
insert into group_test values (40,\'Coding\', \'Samuel\',4000);
insert into group_test values (40,\'Programmer\',\'Susy\',4000);
insert into group_test values (40,\'Architect\', \'Tina\',4000);
insert into group_test values (40,\'Director\', \'Wendy\',4000);
commit;
3)初始化之后的数据情况如下:
SECOOLER@ora11g> set pages 100
SECOOLER@ora11g> select * from group_test;
GROUP_ID JOB NAME SALARY
---------- ---------- ---------- ----------
10 Coding Bruce 1000
10 Programmer Clair 1000
10 Architect Gideon 1000
10 Director Hill 1000
20 Coding Jason 2000
20 Programmer Joey 2000
20 Architect Martin 2000
20 Director Michael 2000
30 Coding Rebecca 3000
30 Programmer Rex 3000
30 Architect Richard 3000
30 Director Sabrina 3000
40 Coding Samuel 4000
40 Programmer Susy 4000
40 Architect Tina 4000
40 Director Wendy 4000
16 rows selected.
2.先看一下普通分组的效果:对group_id进行普通的group by操作---按照小组进行分组
SECOOLER@ora11g> select group_id,sum(salary) from group_test group by group_id;
GROUP_ID SUM(SALARY)
---------- -----------
30 12000
20 8000
40 16000
10 4000
3.对group_id进行普通的roolup操作---按照小组进行分组,同时求总计
SECOOLER@ora11g> select group_id,sum(salary) from group_test group by rollup(group_id);
GROUP_ID SUM(SALARY)
---------- -----------
10 4000
20 8000
30 12000
40 16000
40000
使用Group By语句翻译一下上面的SQL语句如下(union all一个统计所有数据的行):
SECOOLER@ora11g> select group_id,sum(salary) from group_test group by group_id
2 union all
3 select null, sum(salary) from group_test
4 order by 1;
GROUP_ID SUM(SALARY)
---------- -----------
10 4000
20 8000
30 12000
40 16000
40000
4.再看一个rollup两列的情况
SECOOLER@ora11g> select group_id,job,sum(salary) from group_test group by rollup(group_id, job);
GROUP_ID JOB SUM(SALARY)
---------- ---------- -----------
10 Coding 1000
10 Director 1000
10 Architect 1000
10 Programmer 1000
10 4000
20 Coding 2000
20 Director 2000
20 Architect 2000
20 Programmer 2000
20 8000
30 Coding 3000
30 Director 3000
30 Architect 3000
30 Programmer 3000
30 12000
40 Coding 4000
40 Director 4000
40 Architect 4000
40 Programmer 4000
40 16000
40000
21 rows selected.
上面的SQL语句该如何使用Group By进行翻译呢?
答案如下:
SECOOLER@ora11g> select group_id,job,sum(salary) from group_test group by group_id, job
2 union all
3 select group_id,null,sum(salary) from group_test group by group_id
4 union all
5 select null,null,sum(salary) from group_test
6 order by 1,2;
GROUP_ID JOB SUM(SALARY)
---------- ---------- -----------
10 Architect 1000
10 Coding 1000
10 Director 1000
10 Programmer 1000
10 4000
20 Architect 2000
20 Coding 2000
20 Director 2000
20 Programmer 2000
20 8000
30 Architect 3000
30 Coding 3000
30 Director 3000
30 Programmer 3000
30 12000
40 Architect 4000
40 Coding 4000
40 Director 4000
40 Programmer 4000
40 16000
40000
21 rows selected.
5.补充一步,体验一下GROUPING函数的效果
直接看效果就OK啦:
SECOOLER@ora11g> select group_id,job,grouping(GROUP_ID),grouping(JOB),sum(salary) from group_test group by rollup(group_id, job);
GROUP_ID JOB GROUPING(GROUP_ID) GROUPING(JOB) SUM(SALARY)
---------- ---------- ------------------ ------------- -----------
10 Coding 0 0 1000
10 Director 0 0 1000
10 Architect 0 0 1000
10 Programmer 0 0 1000
10 0 1 4000
20 Coding 0 0 2000
20 Director 0 0 2000
20 Architect 0 0 2000
20 Programmer 0 0 2000
20 0 1 8000
30 Coding 0 0 3000
30 Director 0 0 3000
30 Architect 0 0 3000
30 Programmer 0 0 3000
30 0 1 12000
40 Coding 0 0 4000
40 Director 0 0 4000
40 Architect 0 0 4000
40 Programmer 0 0 4000
40 0 1 16000
1 1 40000
21 rows selected.
看出来什么效果了么?
有的同学还是没有看出来,小小的解释一下:
如果显示“1”表示GROUPING函数对应的列(例如JOB字段)是由于ROLLUP函数所产生的空值对应的信息,即对此列进行汇总计算后的结果。
如果显示“0”表示此行对应的这列参未与ROLLUP函数分组汇总活动。
如果还是没有理解清楚,请参见Oracle官方文档中的描述内容:“Using a single column as its argument, GROUPING returns 1 when it encounters a NULL value created by a ROLLUP or CUBE operation. That is, if the NULL indicates the row is a subtotal, GROUPING returns a 1. Any other type of value, including a stored NULL, returns a 0.”
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
转载:http://www.cnblogs.com/lxh1076/p/5697929.html
group by 后使用 rollup 子句总结
group by 后使用 rollup 子句总结
一、如何理解group by 后带 rollup 子句所产生的效果
group by 后带 rollup 子句的功能可以理解为:先按一定的规则产生多种分组,然后按各种分组统计数据(至于统计出的数据是求和还是最大值还是平均值等这就取决于SELECT后的聚合函数)。因此要搞懂group by 后带 rollup 子句的用法主要是搞懂它是如何按一定的规则产生多种分组的。另group by 后带 rollup 子句所返回的结果集,可以理解为各个分组所产生的结果集的并集且没有去掉重复数据。下面举例说明:
1、 对比没有带rollup 的goup by
例:Group by A ,B
产生的分组种数:1种;
即group by A,B
返回结果集:也就是这一种分组的结果集。
2、 带rollup 但 group by 与 rollup 之间没有任何内容
例1:Group by rollup(A ,B)
产生的分组种数:3 种;
第一种:group by A,B
第二种:group by A
第三种:group by NULL
(说明:本没有group by NULL 的写法,在这里指是为了方便说明,而采用之。含义是:没有分组,也就是所有数据做一个统计。例如聚合函数是SUM的话,那就是对所有满足条件的数据进行求和。此写法的含义下同)
返回结果集:为以上三种分组统计结果集的并集且未去掉重复数据。
例2:Group by rollup(A ,B,C)
产生的分组种数:4 种;
第一种:group by A,B,C
第二种:group by A,B
第三种:group by A
第四种:group by NULL
返回结果集:为以上四种分组统计结果集的并集且未去掉重复数据。
3、 带rollup 但 group by 与 rollup 之间还包含有列信息
例1:Group by A , rollup(A ,B)
产生的分组种数:3 种;
第一种:group by A,A,B 等价于 group by A,B
第二种:group by A,A 等价于 group by A
第三种:group by A,NULL 等价于 group by A
返回结果集:为以上三种分组统计结果集的并集且未去掉重复数据。
例2:Group by C , rollup(A ,B)
产生的分组种数:3 种;
第一种:group by C,A,B
第二种:group by C,A
第三种:group by C,NULL 等价于 group by C
返回结果集:为以上三种分组统计结果集的并集且未去掉重复数据。
4、 带rollup 且rollup子句括号内又使用括号对列进行组合
例1:Group by rollup((A ,B))
产生的分组种数:2 种;
第一种:group by A,B
第二种:group by NULL
返回结果集:为以上两种分组统计结果集的并集且未去掉重复数据。
例2:Group by rollup(A ,(B,C))
产生的分组种数:3 种;
第一种:group by A,B,C
第二种:group by A
第三种:group by NULL
返回结果集:为以上三种分组统计结果集的并集且未去掉重复数据。
注:对这种情况,可以理解为几个列被括号括在一起时,就只能被看成一个整体,分组时不需要再细化。因此也可推断rollup括号内也顶多加到一重括号,加多重了应该没有任何意义(这个推断我没有做验证的哦)。
二、与rollup组合使用的其它几个辅助函数
1、grouping()函数
必须接受一列且只能接受一列做为其参数。参数列值为空返回1,参数列值非空返回0。
2、grouping_id()函数
必须接受一列或多列做为其参数。
返回值为按参数排列顺序,依次对各个参数使用grouping()函数,并将结果值依次串成一串二进制数然后再转化为十进制所得到的值。
例如:grouping(A) = 0 ; grouping(B) = 1;
则:grouping_id(A,B) = (01)2 = 1;
grouping_id(B,A) = (10)2 =2;
3、group_id()函数
调用时不需要且不能传入任何参数。
返回值为某个特定的分组出现的重复次数(第一大点中的第3种情况中往往会产生重复的分组)。重复次数从0开始,例如某个分组第一次出现则返回值为0,第二次出现时返回值为1,……,第n次出现返回值为n-1。
注:使用以上三个函数往往是为了过滤掉一部分统计数据,而达到美化统计结果的作用。
三、group by 后带rollup子句与 group by 后带cube子句区别
group by 后带rollup子句与 group by 后带cube子句的唯一区别就是:
带cube子句的group by 会产生更多的分组统计数据。cube后的列有多少种组合(注意组合是与顺序无关的)就会有多少种分组。
例:Group by cube(A ,B,C)
产生的分组种数:8 种;
第一种:group by A,B,C
第二种:group by A,B
第三种:group by A,C
第四种:group by B,C
第五种:group by C
第六种:group by B
第七种:group by A
第八种:group by NULL
返回结果集:为以上八种分组统计结果集的并集且未去掉重复数据。
四、group by 后带grouping sets子句
group by 后带grouping sets子句效果就是只返回小记记录,即只返回按单个列分组后的统计数据,不返回多个列组合分组的统计数据。
例1:Group by grouping sets(A )
产生的分组种数:1 种;
第一种:group by A
返回结果集:即为以上一种分组的统计结果集。
例2:Group by grouping sets(A ,B)
产生的分组种数:2 种;
第一种:group by A
第二种:group by B
返回结果集:为以上两种分组统计结果集的并集且未去掉重复数据。
例3:Group by grouping sets (A ,B,C)
产生的分组种数:3 种;
第一种:group by A
第二种:group by B
第三种:group by C
返回结果集:为以上三种分组统计结果集的并集且未去掉重复数据。
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
转载:http://www.cnblogs.com/fangyz/p/5813916.html
2.grouping( )
grouping函数用来区分NULL值,这里NULL值有2种情况,一是原本表中的数据就为NULL,二是由rollup、cube、grouping sets生成的NULL值。
当为第一种情况中的空值时,grouping(NULL)返回0;当为第二种情况中的空值时,grouping(NULL)返回1。实例如下,从结果中可以看到第二个结果集中原本为null的数据由于grouping函数为1,故显示ROLLUP-NULL字符串。
select teacherAddress,ascriptionInstitute,COUNT(teacherId ) from teacher group by teacherAddress,ascriptionInstitute select teacherAddress,ascriptionInstitute,COUNT(teacherId ) from teacher group by rollup(teacherAddress,ascriptionInstitute) select ISNULL(teacherAddress,case when GROUPING(teacherAddress)=1 then \'ROLLUP-NULL\' end) as teacherAddress, ISNULL(ascriptionInstitute,case when GROUPING(ascriptionInstitute)=1 then \'ROLLUP-NULL\' end) as ascriptionInstitute, COUNT(teacherId ) from teacher group by rollup(teacherAddress,ascriptionInstitute)
以上是关于rollup和grouping函数的主要内容,如果未能解决你的问题,请参考以下文章
[转]详解Oracle高级分组函数(ROLLUP, CUBE, GROUPING SETS)
在oracle里 group by 分组是怎么回事 为啥有时候不加group by说不是单组分组函数?