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. 异常处理_Maven多模块web项目整合ssm+dubbo

    异常如下: [ERROR][org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader. ...

  2. ThinkPHP3.* 模型操作相关函数

    ThinkPHP3.* 版本,大家所不熟知的,且与数据库操作相关的函数做以简单罗列: 1.getLastSql 别名 _sql (鉴于getLastSql比较常用,故出现了别名函数_sql) 2.se ...

  3. 一图搞定【实战Java高并发程序设计】

    来了解下java并发的技术点吧.这里面包括了并发级别.算法.定律,还有开发包.在过去单核CPU时代,单任务在一个时间点只能执行单一程序,随着多核CPU的发展,并行程序开发就显得尤为重要.这本书主要介绍 ...

  4. Navsion二次开发_学习笔记

    CodeUnit Note   This feature is documented in the Navision Application Server Technical White Paper. ...

  5. 模糊测试(fuzz testing)介绍(一)

    模糊测试(fuzz testing)是一类安全性测试的方法.说起安全性测试,大部分人头脑中浮现出的可能是一个标准的“黑客”场景:某个不修边幅.脸色苍白的年轻人,坐在黑暗的房间中,正在熟练地使用各种工具 ...

  6. 老司机学Xamarin系列总目录

    Xamarin开发环境及开发框架初探 Xamarin Forms开发框架二探 (Prism vs MvvmCross) Xamarin Forms开发框架之MvvmCross插件精选 Xamarin开 ...

  7. Lucene系列-FieldCache

    域缓存,加载所有文档中某个特定域的值到内存,便于随机存取该域值. 用途及使用场景 当用户需要访问各文档中某个域的值时,IndexSearcher.doc(docId)获得Document的所有域值,但 ...

  8. java stopwatch 功能

    C#中有一个stopwatch的功能,主要是用来监测程序执行时间的.java之前一直都在用如下方式完成: public static void main(String[] args) { long s ...

  9. 2013 duilib入门简明教程 -- VS环境配置(2)

        既然是入门教程,那当然得基础点,因为搜索duilib相关资料时,发现有些小伙伴到处都是编译错误,以及路径配置错误等等,还有人不知道SVN,然后一个个文件手动下载的.     其实吧,duili ...

  10. 精通visual c++指纹模式识别系统算法及实现

    通过学习,掌握以下几个问题: 1.核心算法,并且向GVF衍生: 2.核心库封装的方法 2016年11月16日06:52:51 昨日实现了梯度场和频率场的计算.最大的感觉就是建立基础代码库的重要性. 如 ...