理解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.)联合使用来得到一个或多个列 ...
随机推荐
- MVVM模式下实现拖拽
在文章开始之前先看一看效果图 我们可以拖拽一个"游戏"给ListBox,并且ListBox也能接受拖拽过来的数据, 但是我们不能拖拽一个"游戏类型"给它. 所以 ...
- WPF中文字体问题
- js小例子(标签页)
运用js写的一个小例子,实现点击不同的标签出现不同的内容: <!DOCTYPE html> <html> <head> <meta chaset=" ...
- 静态局部变量(面向过程的static关键字)
对于一个完整的程序,在内存中的分布情况如下图: 一般程序的由new产生的动态数据存放在堆区,函数内部的自动变量存放在栈区.自动变量一般会随函数的退出而释放空间,静态数据(即使是函数内部的静态局部变量) ...
- Codeforces 682B New Skateboard(DP)
题目大概说给一个数字组成的字符串问有几个子串其代表的数字(可以有前导0)能被4整除. dp[i][m]表示字符串0...i中mod 4为m的后缀的个数 通过在i-1添加str[i]字符转移,或者以st ...
- node.js--HTTP模块
HTTP模块 node.js提供了一个创建自己服务器的方式,用起来很简单,首先引用http模块 //引用HTTP模板 var http = require('http'); 创建服务实例:http.c ...
- 寻找房间中心zz
Finding the Centroid of a Room Boundary It's been a while since my last post and I'm sure most of yo ...
- ggplot2包--R可视化
1.ggplot2发展历程 ggplot2是Hadley在爱荷华州立大学博士期间的作品,也是他博士论文的主题之一,实际上ggplot2还有个前身ggplot,但后来废弃了,某种程度上这也是Hadley ...
- java unicode转中文
public static String unicodeToString(String str) { Pattern pattern = Pattern.compile("(\\\\u(\\ ...
- Android开发环境变量配置总结
每次重装系统或者拿到一台新电脑都得重配Android的环境变量,每次都得上网查,索性就记在这儿吧. “系统属性->高级系统设置->环境变量” 打开环境变量配置窗口. JDK配置: 新建JA ...