设为首页 收藏本站
查看: 386|回复: 0

[经验分享] Oracle的rollup、cube、grouping sets函数

[复制链接]

尚未签到

发表于 2016-7-31 14:15:46 | 显示全部楼层 |阅读模式
  
Oraclegroup by除了基本用法以外,还有3种扩展用法,分别是rollupcubegrouping sets
1 rollup
假设有一个表test,有ABCDE5列。
如果使用group by rollup(A,B,C),首先会对(ABC)进行GROUP BY,然后对(AB)进行GROUP BY,然后是(A)进行GROUP BY,最后对全表进行GROUP BY操作。roll up的意思是“卷起”,这也可以帮助我们理解group by rollup就是对选择的列从右到左以一次少一列的方式进行grouping直到所有列都去掉后的grouping(也就是全表grouping),对于n个参数的rollup,有n+1次的grouping。以下2sql的结果集是一样的:
Select A,B,C,sum(E) from test group by rollup(A,B,C)

Select A,B,C,sum(E) from test group by A,B,C
union all
Select A,B,null,sum(E) from test group by A,B
union all
Select A,null,null,sum(E) from test group by A
union all
Select null,null,null,sum(E) from test
2 cube
cube的意思是立方,对cube的每个参数,都可以理解为取值为参与grouping和不参与grouping两个值的一个维度,然后所有维度取值组合的集合就是grouping的集合,对于n个参数的cube,有2^n次的grouping。如果使用group by cube(A,B,C),,则首先会对(ABC)进行GROUP BY,然后依次是(AB)(AC)(A)(BC)(B)(C),最后对全表进行GROUP BY操作,一共是2^3=8grouping。同rollup一样,也可以用基本的group by加上结果集的union all写出一个与group by cube结果集相同的sql
Select A,B,C,sum(E) from test group by cube(A,B,C);

Select A,B,C,sum(E) from test group by A,B,C
union all
Select A,B,null,sum(E) from test group by A,B
union all
Select A,null,C,sum(E) from test group by A,C
union all
Select A,null,null,sum(E) from test group by A
union all
Select null,B,C,sum(E) from test group by B,C
union all
Select null,B,null,sum(E) from test group by B
union all
Select null,null,C,sum(E) from test group by C
union all
Select null,null,null,sum(E) from test;
3 grouping sets
grouping sets就是对参数中的每个参数做grouping,也就是有几个参数做几次grouping,例如使用group by grouping sets(A,B,C),则对(A),(B),(C)进行group by,如果使用group by grouping sets((A,B),C),则对(A,B),(C)进行group by。甚至grouping by grouping set(A,A)都是语法允许的,也就是对(A)进行2group by,grouping sets的参数允许重复
4 总结
rollup (N+1个分组方案)
cube (2^N个分组方案)
grouping sets (自定义罗列出分组方案)
5 注意点
5.1 机制不同
rollupcube的说明中分别给出了用基本group by加结果集union all给出了结果集相同的sql,但这只是为了理解的方便而给出的sql,并不说明rollupcube与基本group by加结果集union all等价。实际上两者的内部机制是安全不一样的,前者除了写法简洁以外,运行时不需多次扫描表,效率远比后者高。
5.2 集合可运算
3种扩展用法的参数可以是源表中的某一个具体的列,也可以是若干列经过计算而形成的一个新列(比如说A+BA||B),也可以是这两种列的一个集合(例如(A+BC)),对于grouping set更是特殊,可以是空集合(),表示对全表进行group by
5.3 group by 与 rollup, cube组合使用
3Group by的基本用法以及这3种扩展用法可以组合使用,也就是说可以出现group by A,rollup(A,B)这样的用法,oracle将对出现在group by中的每种用法的grouping列集合做笛卡尔积然后对其中的每一个元素做group by。这话说起来挺绕口,举例说明吧,group by A, rollup(A,B),基本用法的grouping集合是(A),rollup(A,B)grouping集合是((A,B),(A),()),两个集合的笛卡尔积集合是((A,A,B),(A,A),(A)),所以会首先对(A,A,B)group by,然后对(A,A)group by,最后对(A)group by。实际上对(A,A,B)group by和对(A,B)group by两者是完全等价的(group by A,A,B结果和group by A,B完全一样),同理对(A,A)group by和对(A)group by也是等价的。简化后的结果就是首先对(A,B)group by,然后对(A)group by,最后再对(A)group by。下面给出两个等价的sql以便理解:
Select A,B,sum(E) from test1 group by A, rollup(A,B);

Select A,B,sum(E) from test1 group by A,B
Union all
Select A,null,sum(E) from test1 group by A
Union all
Select A,null,sum(E) from test1 group by A;
6 grouping()、grouping_id()、group_id()
6.1 grouping()
参数只有一个,而且必须为group by中出现的某一列,表示结果集的一行是否对该列做了grouping。对于对该列做了grouping的行而言,grouping()=0,反之为1
6.2 grouping_id()
参数可以是多个,但必须为group by中出现的列。Grouping_id()的返回值其实就是参数中的每列的grouping()值的二进制向量,例如如果grouping(A)=1grouping(B)=0,则grouping_id(A,B)的返回值就是二进制的10,转成10进制就是2
6.3 group_id()
无参数。见上面的说明3),group by对某些列的集合会进行重复的grouping,而实际上绝大多数情况下对结果集中的这些重复行是不需要的,那就必须有办法剔出这些重复grouping的行。当结果集中有n条重复grouping而形成的行时,每行的group_id()分别是0,1,,n,这样我们在条件中加入一个group_id()<1就可以剔出这些重复grouping的行了。
7 示例
7.1 建表与数据
SQL> create table test(department_id number, a varchar2(20), b varchar2(20));

Table created

SQL> insert into test values(10, 'A', 'B');

1 row inserted

SQL> commit;

Commit complete
7.2 查询语句
select department_id,

a,

b,

grouping(department_id),

grouping(a),

grouping(b)

from test

group by rollup(department_id, a, b)

order by 4, 5, 6;


select department_id,

a,

b,

grouping(department_id),

grouping(a),

grouping(b)

from test

group by cube(department_id, a, b)

order by 4, 5, 6;



  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-251509-1-1.html 上篇帖子: oracle 创建表及其相关约束 下篇帖子: oracle系统表的查询字典
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表