理解group by 语句的扩展使用
在SQL的开发中我们会经常使用group by语句对数据进行分组统计,然而在一些复杂的BI报表开发中会常遇到更
复杂的分组需求,单单使用group by 就不能解决我们的问题了,这时我们就需要学习了解一下在group by 语句上的一些扩展使用,下面我们就来学习一下rollup、cube、grouping sets语句的使用。
1.group by
SQL> select a.dname,b.job,sum(b.sal) sum_sal
from dept a,emp b
where a.deptno=b.deptno
group by a.dname,b.job; DNAME JOB SUM_SAL
-------------- --------- ----------
SALES MANAGER
SALES CLERK
ACCOUNTING MANAGER
ACCOUNTING PRESIDENT
ACCOUNTING CLERK
RESEARCH MANAGER
SALES SALESMAN
RESEARCH ANALYST
RESEARCH CLERK rows selected
可以看到以上数据中我们按照部门名和职位名进行了分组,然后求出每组内的工资数。
假如现在我们有一个需求,需要在这个查询中增加一个不同部门间的工资总和,那么这个SQL该怎么写:
我们是不是会这样写:
SQL> select * from (
SELECT a.dname,b.job,SUM(b.sal) sum_sal
FROM dept a,emp b
WHERE a.deptno = b.deptno
GROUP BY a.dname,b.job
UNION ALL
--部门的小计
SELECT a.dname,NULL, SUM(b.sal) sum_sal
FROM dept a,emp b
WHERE a.deptno = b.deptno
GROUP BY a.dname
UNION ALL
--所有部门总的合计
SELECT NULL,NULL, SUM(b.sal) sum_sal
FROM dept a,emp b
WHERE a.deptno = b.deptno)
order by dname; DNAME JOB SUM_SAL
-------------- --------- ----------
ACCOUNTING
ACCOUNTING MANAGER
ACCOUNTING PRESIDENT
ACCOUNTING CLERK
RESEARCH CLERK
RESEARCH MANAGER
RESEARCH
RESEARCH ANALYST
SALES CLERK
SALES MANAGER
SALES SALESMAN
SALES rows selected
可以看到上面的SQL写法实现了之前的需求,但是执行效率将非常低,dept表和emp表将会被多次扫描,
能否一次扫描就能搞定这个事哪,答案的肯定的,使用rollup函数。
2.group by rollup
SQL> select a.dname,b.job,sum(b.sal) sum_sal
from dept a,emp b
where a.deptno=b.deptno
group by rollup(a.dname,b.job); DNAME JOB SUM_SAL
-------------- --------- ----------
SALES CLERK
SALES MANAGER
SALES SALESMAN
SALES
RESEARCH CLERK
RESEARCH ANALYST
RESEARCH MANAGER
RESEARCH
ACCOUNTING CLERK
ACCOUNTING MANAGER
ACCOUNTING PRESIDENT
ACCOUNTING rows selected
通过上面的查询可以看到使用rollup函数我们一次就实现了上面的需求,而且dept表和emp表将只会被扫描一次,可以通过查询执行计划要来验证(略)。
group by rollup(a.dname,b.job)
分组是这样的:
1.首先对a.dname,b.job进行联合分组,求出sum
2.其次对a.dname进行分组,求出sum
3.最后按全表进行分组求出sum
可能有些人对于上面union all的写法还能接受,决定实现起来不难而且很好理解,但是我要说的是如果是需求再改变,在增加求出对雇佣年份的统计,是不是又要union all了,这就显得sql很冗肿了,效率下降,你还能接受吗?如果现在我们的需求又改变了,我们(a.dname,b.job)在前面的基础上增加对 b.job进行分组求和,这时该怎么做那,。。。。这时就需要我们使用cube函数。
3.group by cube
SQL> select a.dname,b.job,sum(b.sal) sum_sal
from dept a,emp b
where a.deptno=b.deptno
group by cube(a.dname,b.job); DNAME JOB SUM_SAL
-------------- --------- ---------- CLERK
ANALYST
MANAGER
SALESMAN
PRESIDENT
SALES
SALES CLERK
SALES MANAGER
SALES SALESMAN
RESEARCH
RESEARCH CLERK
RESEARCH ANALYST
RESEARCH MANAGER
ACCOUNTING
ACCOUNTING CLERK
ACCOUNTING MANAGER
ACCOUNTING PRESIDENT rows selected
通过上面的sql查询我们发现cube函数是rollup函数基础上更细化的分组,在rollup的基础上又增加了对job的分组,是不是这样的那??? 通过上面的查询发现使用rollup函数有13条数据,相同数据的情况下使用cube函数有18条数据,那么多出的5条数据就是对job的分组,查询一下job有种:
SQL> select distinct job from emp; JOB
---------
CLERK
SALESMAN
PRESIDENT
MANAGER
ANALYST
可以看到正好有5种job,验证了上面的问题。
group by cube(a.dname,b.job)
分组是这样的:
1.首先按照a.dname,b.job进行分组,求聚合函数的值
2.其次按照a.dname进行分组,求聚合函数的值
3.再次按照b.job进行分组,求聚合函数的值
4.最后对全表进行分组,求聚合函数的值
如果是三列数据那:
group by cube(a.dname,b.job,b.hiredate)
分组是这样的:
1.首先按照a.dname,b.job,b.hiredate进行分组,求聚合函数的值
2.然后按照a.dname,b.job进行分组,求聚合函数的值
3.然后按照a.dname,b.hiredate进行分组,求聚合函数的值
4.然后按照b.job,b.hiredate进行分组,求聚合函数的值
5.然后按照a.dname进行分组,求聚合函数的值
6.然后按照b.job进行分组,求聚合函数的值
7.然后按照b.hiredate进行分组,求聚合函数的值
8.最后按照全表进行分组,求聚合函数的值
例如:
SQL> select a.dname,b.job,b.hiredate,sum(b.sal) sum_sal
from dept a,emp b
where a.deptno=b.deptno
group by cube(a.dname,b.job,b.hiredate); DNAME JOB HIREDATE SUM_SAL
-------------- --------- ----------- ---------- //
//
//
//
//
//
//
//
//
//
//
//
//
CLERK
CLERK //
CLERK //
CLERK //
CLERK //
ANALYST
ANALYST //
ANALYST //
MANAGER
MANAGER //
MANAGER //
MANAGER //
SALESMAN
SALESMAN //
SALESMAN //
SALESMAN //
SALESMAN //
PRESIDENT
PRESIDENT //
SALES
SALES //
SALES //
SALES //
SALES //
SALES //
SALES //
SALES CLERK
SALES CLERK //
SALES MANAGER
SALES MANAGER //
SALES SALESMAN
SALES SALESMAN //
SALES SALESMAN //
SALES SALESMAN //
SALES SALESMAN //
RESEARCH
RESEARCH //
RESEARCH //
RESEARCH //
RESEARCH //
RESEARCH //
RESEARCH CLERK
RESEARCH CLERK //
RESEARCH CLERK //
RESEARCH ANALYST
RESEARCH ANALYST //
RESEARCH ANALYST //
RESEARCH MANAGER
RESEARCH MANAGER //
ACCOUNTING
ACCOUNTING //
ACCOUNTING //
ACCOUNTING //
ACCOUNTING CLERK
ACCOUNTING CLERK //
ACCOUNTING MANAGER
ACCOUNTING MANAGER //
ACCOUNTING PRESIDENT
ACCOUNTING PRESIDENT // rows selected
如果分别按照a.dname,b.job,b.hiredate进行分组求和,我们是不是可以放在一个SQL中实现,
答案的可以的,我们可以利用grouping sets函数
4.group by grouping sets
SQL> select a.dname,b.job,b.hiredate,sum(b.sal) sum_sal
from dept a,emp b
where a.deptno=b.deptno
group by grouping sets (a.dname,b.job,b.hiredate); DNAME JOB HIREDATE SUM_SAL
-------------- --------- ----------- ----------
//
//
//
//
//
//
//
//
//
//
//
//
//
CLERK
SALESMAN
PRESIDENT
MANAGER
ANALYST
ACCOUNTING
RESEARCH
SALES rows selected
通过上面的查询我们就很一目了然看到他们的分组规律。
group by grouping sets (a.dname,b.job,b.hiredate)
分组是这样的:
1.首先按照a.dname进行分组,求聚合函数的值
2.其次按照b.job进行分组,求聚合函数的值
1.最后按照b.hiredate进行分组,求聚合函数的值
5.总结归类下
Rollup是在group by的基础上再进行分级的汇总,例如:Rollup(A,B,C)的分组顺序是:
(A,B,C)
(A,B)
(A)
最后对全表进行group by 分组。
Cube是在Rollup的基础上再进行更加细粒度的汇总,例如:cube(A,B,C)它的分组顺序是:
(A,B,C)
(A,B)
(A,C)
(A)
(B,C)
(B)
(C)
最后对全表进行group by 分组。
Grouping sets与rollup和cube不同,它只是对单列进行分组,例如grouping sets(A,B,C)的分组顺序是:
(A)
(B)
(C)
可参考:
http://love-flying-snow.iteye.com/blog/573083
理解group by 语句的扩展使用的更多相关文章
- [Oracle] Group By 语句的扩展 - Rollup、Cube和Grouping Sets
常常写SQL语句的人应该知道Group by语句的主要使用方法是进行分类汇总,以下是一种它最常见的使用方法(依据部门.职位分别统计业绩): SELECT a.dname,b.job,SUM(b.sal ...
- 深入理解group by 语句的执行顺序 from→where→group by→select(含聚合函数)
由于之前没有对group by 语句的执行顺序(执行原理)做深入的了解,所以导致在实际应用过程中出现了一些问题.举个简单的粟子,比如一个表testA中的所有数据如下图: 我现在想从testA中查询us ...
- 如何理解group by语句
参考文章: https://blog.csdn.net/hao1066821456/article/details/69556644 如何实现一对多关系,得到一行多列的显示方式: group by可以 ...
- 可以这样去理解group by和聚合函数
写在前面的话:用了好久group by,今天早上一觉醒来,突然感觉group by好陌生,总有个筋别不过来,为什么不能够select * from Table group by id,为什么一定不能是 ...
- 可以这样去理解group by和聚合函数(转)
http://www.cnblogs.com/wuguanglei/p/4229938.html 写在前面的话:用了好久group by,今天早上一觉醒来,突然感觉group by好陌生,总有个筋别不 ...
- 一文让你彻底理解group by和聚合函数
知道group by是进行分组查询,但是一直觉得对其理解得不够透彻,在网上扒了一篇文章,我认为写得非常好. 为什么不能够select * from Table group by id,为什么一定不能是 ...
- SQL GROUP BY 语句
合计函数 (比如 SUM) 常常需要添加 GROUP BY 语句. GROUP BY 语句 GROUP BY 语句用于结合合计函数,根据一个或多个列对结果集进行分组. SQL GROUP BY 语法 ...
- (转载)SQL语句中Group by语句的详细介绍
转自:http://blog.163.com/yuer_d/blog/static/76761152201010203719835 SQL语句中Group by语句的详细介绍 ...
- GROUP BY语句与HAVING语句的使用
一.GROUP BY GROUP BY语句用来与聚合函数(aggregate functions such as COUNT, SUM, AVG, MIN, or MAX.)联合使用来得到一个或多个列 ...
随机推荐
- 【SQL Server】数据库是单个用户的 无法顺利进行操作 怎么解决
1.打开数据库 2.新建查询 ,输入以下的SQL 语句 DECLARE @SQL VARCHAR(MAX); SET @SQL='' SELECT @SQL=@SQL+'; KILL '+RTRIM( ...
- Eclipse配置Lifery SDK步骤与错误解决。
第一步.我们先去官网下载我们要用的东西 1.Eclipse 2.SDK 3.Tomcat 这是官网下载地址-->https://www.liferay.com/zh/downloads 下面是图 ...
- PDA手持移动POS销售开单软件(网络版)、PDA手持设备小票机
背景描述: 一家大中型批发及门店销售企业,经销多种冻食品,业务范围覆盖周边众多区域和城市.成立以来,随着业务量的扩大,产品销售分两大渠道:多门店销售和仓库批发,各门店每天都有大量的零散客户和老客户进行 ...
- WPF拖放功能实现zz
写在前面:本文为即兴而作,因此难免有疏漏和词不达意的地方.在这里,非常期望您提供评论,分享您的想法和建议. 这是一篇介绍如何在WPF中实现拖放功能的短文. 首先要读者清楚的一件事情是:拖放主要分为拖放 ...
- Prerequisites?[HDU1144]
Prerequisites?Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total ...
- 拓展企业VR培训业务,这家VR训练公司StriVR完成500万美元融资!
虚拟现实初创公司StriVR最近发布了新的企业VR训练产品项目,并宣布在刚刚结束的首轮融资中获得500万美元投资.由Signia Venture Partners领投,宝马i Venturesi.Ad ...
- webpack练手项目之easySlide(一):初探webpack (转)
最近在学习webpack,正好拿了之前做的一个小组件,图片轮播来做了下练手,让我们一起来初步感受下webpack的神奇魅力. webpack是一个前端的打包管理工具,大家可以前往:http:/ ...
- android 内部缓存器(手机自带的存储空间中的当前包文件的路径)
关于Context中: 1. getCacheDir()方法用于获取/data/data/<application package>/cache目录 2. getFilesDir()方法用 ...
- Android 大位图加载
说明:没对图片进行缓存处理,只是使用软引用进行位图资源的释放,从而避免内存泄漏. 对位图进行解码显示: public Bitmap decodeBitmap(Resources resources, ...
- topcoder SRM 610 DIV2 DivideByZero
题目的意思是给你一组数,然后不断的进行除法(注意是大数除以小数),然后将得到的结果加入这组数种然后继续进行除法, 直到没有新添加的数为止 此题按照提议模拟即可 注意要保持元素的不同 int Count ...