GROUP BY的扩展主要包括ROLLUP,CUBE,GROUPING SETS三种形式。

ROLLUP

rollup相对于简单的分组合计增加了小计和合计,解释起来会比较抽象,下面我们来看看具体事例。

例1,统计不同部门工资的总和和所有部门工资的总和。

SQL> select deptno,sum(sal) from emp group by rollup(deptno);

    DEPTNO   SUM(SAL)
---------- ----------
10 8750
20 10875
30 9400
29025

例2,该例中先对deptno进行分组,再对job进行分组

SQL> select deptno,job,sum(sal) from emp group by rollup(deptno,job);

    DEPTNO JOB           SUM(SAL)
---------- --------- ----------
10 CLERK 1300 --10号部门中JOB为CLERK的工资的总和
10 MANAGER 2450
10 PRESIDENT 5000
10 8750 --10号所有工种工资的总和
20 CLERK 1900
20 ANALYST 6000
20 MANAGER 2975
20 10875
30 CLERK 950
30 MANAGER 2850
30 SALESMAN 5600
30 9400
29025 --所有部门,所有工种工资的总和
13 rows selected.

如果要用普通的分组函数实现,可用UNION ALL语句:

--实现单个部门,单个工种的工资的总和
select deptno,job,sum(sal) from emp group by deptno,job
union all
--实现单个部门工资的总和
select deptno,null,sum(sal) from emp group by deptno
union all
--实现所有部门工资的总和
select null,null,sum(sal) from emp
order by 1,2

下面我们分别来看看两者的执行计划及统计信息,

ROLLUP语句:

Execution Plan
-----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 11 | 132 | 3 (34)| 00:00:01 |
| 1 | SORT GROUP BY ROLLUP| | 11 | 132 | 3 (34)| 00:00:01 |
| 2 | TABLE ACCESS FULL | EMP | 14 | 168 | 2 (0)| 00:00:01 |
-----------------------------------------------------------------------------
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
2 consistent gets
0 physical reads
0 redo size
895 bytes sent via SQL*Net to client
519 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
13 rows processed

UNION ALL语句:

Execution Plan
-----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 15 | 150 | 9 (34)| 00:00:01 |
| 1 | SORT ORDER BY | | 15 | 150 | 8 (75)| 00:00:01 |
| 2 | UNION-ALL | | | | | |
| 3 | HASH GROUP BY | | 11 | 132 | 3 (34)| 00:00:01 |
| 4 | TABLE ACCESS FULL| EMP | 14 | 168 | 2 (0)| 00:00:01 |
| 5 | HASH GROUP BY | | 3 | 15 | 3 (34)| 00:00:01 |
| 6 | TABLE ACCESS FULL| EMP | 14 | 70 | 2 (0)| 00:00:01 |
| 7 | SORT AGGREGATE | | 1 | 3 | | |
| 8 | TABLE ACCESS FULL| EMP | 14 | 42 | 2 (0)| 00:00:01 |
-----------------------------------------------------------------------------

Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
6 consistent gets
0 physical reads
0 redo size
895 bytes sent via SQL*Net to client
519 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
13 rows processed

不难看出,相同的功能实现,ROLLUP相对于UNION ALL效率有了极大的提升。

CUBE

cube相对于rollup,结果输出更加详细。

例1,在本例中还不是很明显。

SQL> select deptno,sum(sal) from emp group by cube(deptno);

    DEPTNO   SUM(SAL)
---------- ----------
29025
10 8750
20 10875
30 9400

例2,相对于rollup,cube还对工种这一列进行了专门的汇总。

SQL> select deptno,job,sum(sal) from emp group by cube(deptno,job);

    DEPTNO JOB           SUM(SAL)
---------- --------- ----------
29025
CLERK 4150
ANALYST 6000
MANAGER 8275
SALESMAN 5600
PRESIDENT 5000
10 8750
10 CLERK 1300
10 MANAGER 2450
10 PRESIDENT 5000
20 10875
20 CLERK 1900
20 ANALYST 6000
20 MANAGER 2975
30 9400
30 CLERK 950
30 MANAGER 2850
30 SALESMAN 5600
18 rows selected.

GROUPING SETS

GROUPING SETS相对于ROLLUP和CUBE,结果是分类统计的,可读性更好一些。

例1:

SQL> select deptno,job,to_char(hiredate,'yyyy')hireyear,sum(sal) from emp group by grouping sets(deptno,job,to_char(hiredate,'yyyy'));

    DEPTNO JOB         HIRE   SUM(SAL)
---------- --------- ---- ----------
CLERK 4150
SALESMAN 5600
PRESIDENT 5000
MANAGER 8275
ANALYST 6000
30 9400
20 10875
10 8750
1987 4100
1980 800
1982 1300
1981 22825

例2:

SQL> select deptno,job,sum(sal) from emp group by grouping sets(deptno,job);

    DEPTNO JOB           SUM(SAL)
---------- --------- ----------
CLERK 4150
SALESMAN 5600
PRESIDENT 5000
MANAGER 8275
ANALYST 6000
30 9400
20 10875
10 8750
8 rows selected.

对于该例,如何用UNION ALL实现呢?

select null deptno,job,sum(sal) from emp group by job
union all
select deptno,null,sum(sal) from emp group by deptno;

两者的执行计划及统计信息分别如下:

GROUPING SETS:

Execution Plan
--------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 11 | 352 | 10 (20)| 00:00:01 |
| 1 | TEMP TABLE TRANSFORMATION | | | | | |
| 2 | LOAD AS SELECT | SYS_TEMP_0FD9D6795_E71F79 | | | | |
| 3 | TABLE ACCESS FULL | EMP | 14 | 168 | 2 (0)| 00:00:01 |
| 4 | LOAD AS SELECT | SYS_TEMP_0FD9D6796_E71F79 | | | | |
| 5 | HASH GROUP BY | | 1 | 19 | 3 (34)| 00:00:01 |
| 6 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6795_E71F79 | 1 | 19 | 2 (0)| 00:00:01 |
| 7 | LOAD AS SELECT | SYS_TEMP_0FD9D6796_E71F79 | | | | |
| 8 | HASH GROUP BY | | 1 | 26 | 3 (34)| 00:00:01 |
| 9 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6795_E71F79 | 1 | 26 | 2 (0)| 00:00:01 |
| 10 | VIEW | | 1 | 32 | 2 (0)| 00:00:01 |
| 11 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6796_E71F79 | 1 | 32 | 2 (0)| 00:00:01 |
--------------------------------------------------------------------------------------------------------
Statistics
----------------------------------------------------------
4 recursive calls
24 db block gets
17 consistent gets
3 physical reads
1596 redo size
819 bytes sent via SQL*Net to client
519 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
8 rows processed

UNION ALL:

----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 8 | 65 | 6 (67)| 00:00:01 |
| 1 | UNION-ALL | | | | | |
| 2 | HASH GROUP BY | | 5 | 50 | 3 (34)| 00:00:01 |
| 3 | TABLE ACCESS FULL| EMP | 14 | 140 | 2 (0)| 00:00:01 |
| 4 | HASH GROUP BY | | 3 | 15 | 3 (34)| 00:00:01 |
| 5 | TABLE ACCESS FULL| EMP | 14 | 70 | 2 (0)| 00:00:01 |
---------------------------------------------------------------------------- Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
4 consistent gets
0 physical reads
0 redo size
819 bytes sent via SQL*Net to client
519 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
8 rows processed

和rollup不同的是,grouping sets的效率竟然比同等功能的union all语句低,这实现有点出乎意料。看来,也不可盲目应用Oracle提供的方案,至少,在本例中是如此。

GROUP BY的扩展的更多相关文章

  1. 报表开发之扩展GROUP BY

    在实际运用中.比方在数据仓库中,常常须要对数据进行多维分析.不仅须要标准分组的结果(相当于 GROUP BY),还须要不同维度的小计(简单 GROUP BY 中取部分列分组)和合计(不分组).从而 提 ...

  2. mysql5.5手册读书日记(3)

    <?php /* MySQL_5.5中文参考手册 587开始 与GROUP BY子句同时使用的函数和修改程序 12.10.1. GROUP BY(聚合)函数 12.10.2. GROUP BY修 ...

  3. oracle 高级分组

    oracle 高级分组 博客分类: 数据库基础 oraclesql  10.高级分组 本章目标: 对于增强的group by需要掌握: 1.使用rollup(也就是roll up累计的意思)操作产生s ...

  4. spark2.2 DataFrame的一些算子操作

    Spark Session中的DataFrame类似于一张关系型数据表.在关系型数据库中对单表或进行的查询操作,在DataFrame中都可以通过调用其API接口来实现.可以参考,Scala提供的Dat ...

  5. Spark-SQL之DataFrame操作大全

    Spark SQL中的DataFrame类似于一张关系型数据表.在关系型数据库中对单表或进行的查询操作,在DataFrame中都可以通过调用其API接口来实现.可以参考,Scala提供的DataFra ...

  6. python新手菜鸟之基础篇

    s=0 for i in range(1,101): s += i else: print(s) def main(n): '''打印菱形图形''' for i in range(n): print( ...

  7. Spark-SQL之DataFrame操作

    Spark SQL中的DataFrame类似于一张关系型数据表.在关系型数据库中对单表或进行的查询操作,在DataFrame中都可以通过调用其API接口来实现.可以参考,Scala提供的DataFra ...

  8. Linux系统编程【转】

    转自:https://blog.csdn.net/majiakun1/article/details/8558308 一.Linux系统编程概论 1.1 系统编程基石 syscall: libc:标准 ...

  9. [转]详解Oracle高级分组函数(ROLLUP, CUBE, GROUPING SETS)

    原文地址:http://blog.csdn.net/u014558001/article/details/42387929 本文主要讲解 ROLLUP, CUBE, GROUPING SETS的主要用 ...

随机推荐

  1. Storm 中什么是-acker,acker工作流程介绍

    概述 我们知道storm一个很重要的特性是它能够保证你发出的每条消息都会被完整处理, 完整处理的意思是指: 一个tuple被完全处理的意思是: 这个tuple以及由这个tuple所导致的所有的tupl ...

  2. iOS中 将 颜色转化成图片

    定义一个类方法: 声明: + (UIImage *)imageFromColor:(UIColor *)color; 实现: + (UIImage *)imageFromColor:(UIColor ...

  3. SubVersion Ubuntu

    UbuntuサーバにSubversionを入れる Linux, 開発ツール |    Ubuntuサーバが無事に動いたので.続いてSubversionを入れてみる. こんな感じの環境を考える. Apa ...

  4. sqlplus运行sql文件

    当sql文件的数据比较多的时候,pl/sql运行比较慢,可以通过oracle的sqlplus进行导入: sqlplus user/password@tnsname@sqlfile.sql; 注意如果文 ...

  5. codeforces 360 E - The Values You Can Make

    E - The Values You Can Make Description Pari wants to buy an expensive chocolate from Arya. She has  ...

  6. C# winform安装部署(转载)

    c# winform 程序打包部署 核心总结: 1.建议在完成的要打包的项目外,另建解决方案建立安装部署项目(而不是在同一个解决方案内新建),在解决方案上右击-〉添加-〉现有项目-〉选择你要打包的项目 ...

  7. [Android] 时间Time Date 以及Location中gettime

    import android.text.format.Time; 还有一个是Date Location中的gettime, 这几个每个默认的格式都不一样,直接输出字符串各自得到了不同 比如按照获取当前 ...

  8. jquery/zepto 圣诞节雪花飞扬

    下载地址: http://www.html5tricks.com/jquery-html5-christ-snow.html 演示地址: http://www.html5tricks.com/jque ...

  9. wpf之mvvm基类

    当我们用MVVM设计模式的时候要实现INotifyPropertyChanged,每次都要实现这个接口比较麻烦,所以基类的作用就体现出来了.代码如下:   1 2 3 4 5 6 7 8 9 10 1 ...

  10. 基于ajax与msmq技术的消息推送功能实现

    周末在家捣鼓了一下消息推送的简单例子,其实也没什么技术含量,欢迎大伙拍砖.我设计的这个推送demo是基于ajax长轮询+msmq消息队列来实现的,具体交互过程如下图: 先说说这个ajax长轮询,多长时 ...