oracle中的roll up,oracle group by 与roll up,cube,grouping sets,grouping_id联合使用

转自:http://blog.sina.com.cn/s/blog_5f0fbdee0100saw3.html

Oracle的group by除了基本用法以外,还有3种扩展用法,分别是rollup、cube、grouping sets。

1 rollup

假设有一个表test,有A、B、C、D、E5列。

如果使用group by rollup(A,B,C),首先会对(A、B、C)进行GROUP BY,然后对(A、B)进行GROUP

BY,然后是(A)进行GROUP BY,最后对全表进行GROUP BY操作。roll up的意思是“卷起”,这也可以帮助我们理解group by

rollup就是对选择的列从右到左以一次少一列的方式进行grouping直到所有列都去掉后的grouping(也就是全表grouping),对于n个参数的rollup,有n+1次的grouping。以下2个sql的结果集是一样的:

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),,则首先会对(A、B、C)进行GROUP

BY,然后依次是(A、B),(A、C),(A),(B、C),(B),(C),最后对全表进行GROUP

BY操作,一共是2^3=8次grouping。同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)进行2次group by,grouping sets的参数允许重复

4 总结

rollup   (N+1个分组方案)

cube   (2^N个分组方案)

grouping sets (自定义罗列出分组方案)

5 注意点

5.1 机制不同

在rollup和cube的说明中分别给出了用基本group by加结果集union

all给出了结果集相同的sql,但这只是为了理解的方便而给出的sql,并不说明rollup和cube与基本group by加结果集union

all等价。实际上两者的内部机制是安全不一样的,前者除了写法简洁以外,运行时不需多次扫描表,效率远比后者高。

5.2 集合可运算

3种扩展用法的参数可以是源表中的某一个具体的列,也可以是若干列经过计算而形成的一个新列(比如说A+B,A||B),也可以是这两种列的一个集合(例如(A+B,C)),对于grouping

set更是特殊,可以是空集合(),表示对全表进行group by。

5.3 group by 与 rollup, cube组合使用

3)Group 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)=1,grouping(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;

Grouping函数:

可以接受一列,返回0或1。如果列值为空,则返回1,非空则返回0。它只能在rollup和或cube函数中使用,因为在统计中显示“全部”的那一项统计值时,那一项的标签通常是空的,这时grouping就非常有用,还可以在grouping的基础上进行decode,

case等进行美化。

SQL> select

grouping(index_type) g_ind, grouping(status) g_st, index_type, status,

count(*)

2 from t group by rollup(index_type, status) order by

1, 2;

G_IND G_ST

INDEX_TYPE

STATUS COUNT(*)

---------- ----------

--------------------------- --------

----------

0 0

LOB

N/A

1

0 0

LOB

VALID

572

0 0 FUNCTION-BASED

NORMAL

VALID

17

0 0 FUNCTION-BASED

DOMAIN

VALID

1

0 0 IOT -

TOP

VALID

115

0 0

CLUSTER

VALID

10

0 0

NORMAL

VALID

4557

0 0

NORMAL

N/A

56

0 0

DOMAIN

VALID

1

0 0

BITMAP

VALID

8

0 0

BITMAP

N/A

7

0 1 IOT -

TOP

115

0 1 FUNCTION-BASED

DOMAIN

1

0 1

DOMAIN

1

0 1

CLUSTER

10

0 1

BITMAP

15

0 1 FUNCTION-BASED

NORMAL

17

0 1

NORMAL

4613

0 1

LOB

573

1

1

5345

20 rows selected

Grouping_id函数:

比grouping还强点,可以接收多个列,这几个列都不为空时,返回0,只要有一个为空,则返回1,如果都为空,则返回3。

下面这条查询把grouping_id牛刀杀鸡,当做grouping用了,可以看到结果跟用grouping是完全一样。

SQL> select

grouping_id(index_type) g_ind, grouping_id(status) g_st, index_type, status,

count(*)

2 from t group by rollup(index_type, status) order by

1, 2;

G_IND G_ST

INDEX_TYPE

STATUS COUNT(*)

---------- ----------

--------------------------- --------

----------

0 0

LOB

N/A

1

0 0

LOB

VALID

572

0 0 FUNCTION-BASED

NORMAL

VALID

17

0 0 FUNCTION-BASED

DOMAIN

VALID

1

0 0 IOT -

TOP

VALID

115

0 0

CLUSTER

VALID

10

0 0

NORMAL

VALID

4557

0 0

NORMAL

N/A

56

0 0

DOMAIN

VALID

1

0 0

BITMAP

VALID

8

0 0

BITMAP

N/A

7

0 1 IOT -

TOP

115

0 1 FUNCTION-BASED

DOMAIN

1

0 1

DOMAIN

1

0 1

CLUSTER

10

0 1

BITMAP

15

0 1 FUNCTION-BASED

NORMAL

17

0 1

NORMAL

4613

0 1

LOB

573

1

1

5345

20 rows selected

下面这条查询才体现了grouping_id的作用。

SQL> select

grouping_id(index_type, status) g_st, index_type, status, count(*)

2 from t group by rollup(index_type, status) order by 1, 2;

G_ST

INDEX_TYPE

STATUS COUNT(*)

----------

--------------------------- --------

----------

0

BITMAP

VALID

8

0

BITMAP

N/A

7

0

CLUSTER

VALID

10

0

DOMAIN

VALID

1

0 FUNCTION-BASED

DOMAIN

VALID

1

0 FUNCTION-BASED

NORMAL

VALID

17

0 IOT -

TOP

VALID

115

0

LOB

N/A

1

0

LOB

VALID

572

0

NORMAL

N/A

56

0

NORMAL

VALID

4557

1

BITMAP

15

1

CLUSTER

10

1

DOMAIN

1

1 FUNCTION-BASED

DOMAIN

1

1 FUNCTION-BASED

NORMAL

17

1 IOT -

TOP

115

1

LOB

573

1

NORMAL

4613

3 %

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值