Oracle分组函数之ROLLUP魅力

前端之家收集整理的这篇文章主要介绍了Oracle分组函数之ROLLUP魅力前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

iamlaosong文

经常用Excel的人都知道分类汇总功能,rollup函数就可以实现这个分类汇总。以前都是简单的是用group by的分组功能,没想到还有这个rollup函数一说,试了一下,效果真的不错。rollup是对group by的扩展,因此,它只能出现在group by子句中,依赖于分组的列,对每个分组会生成汇总数据,rollup和group by联合一起使用,达到了按group by列顺序分组,并且实现小计和合计的功能

类似的功能还有grouping sets和cube两个函数grouping sets统计每个分组列,cube则统计分组列的每种组合。

rollup分组还是有序的,先全部分组,然后对每个分组小计,最后合计,使处理结果更清楚。rollup中列的顺序不同,则统计的结果不同,因为它是按列从右递减分组的,如下图:


下面是一篇介绍这个功能的网文,原文链接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','Architect','Gideon','Director','Hill',1000);

insert into group_test values (20,'Jason',2000);
insert into group_test values (20,'Joey','Martin','Michael',2000);

insert into group_test values (30,'Rebecca',3000);
insert into group_test values (30,'Rex','Richard','Sabrina',3000);

insert into group_test values (40,'Samuel',4000);
insert into group_test values (40,'Susy','Tina','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,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,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,grouping(GROUP_ID),grouping(JOB),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,GROUPINGreturns 1 when it encounters aNULLvalue created by aROLLUPorCUBEoperation. That is,if theNULLindicates the row is a subtotal,GROUPINGreturns a 1. Any other type of value,including a storedNULL,returns a 0.


6.小结
ROLLUP在数据统计和报表生成过程中带来极大的便利,而且效率比起来Group By + Union组合方法效率高得多。这也体现了Oracle在sql统计分析上人性化、自动化、高效率的特点。

ROLLUP与GROUP BY的关系可以参考Oracle官方文档中的例子,链接如下:《ROLLUP Extension to GROUP BY》http://docs.oracle.com/cd/E11882_01/server.112/e25554/aggreg.htm#DWHSG8608

猜你在找的Oracle相关文章