理解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.)联合使用来得到一个或多个列 ...
随机推荐
- opengl典型例程立方体投影与地图绘制
立方体投影 http://www.cnblogs.com/opengl/p/3790450.html 地图绘制 http://www.cnblogs.com/opengl/p/3790354.html
- 关于CSS动画效果的图片展示
animation:帧动画 animation-name:定义绑定Keyframes的动画名称 @keyframes XXX 定义动画,里面是动画具体内容 animation-duration:过渡动 ...
- 纯css实现两列等高
<!doctype html> <html> <head> <meta /> <title>Title</title> < ...
- shell-bash学习01基础、打印、环境变量
基础 终端提示符: username@hostname$; $: 一般用户 #:root用户 运行脚本 Bash执行: * bash script.sh; 直接运行: 脚本开头添加shebang起始: ...
- js-原型以及继承小案例
function human(name,tall){ this.name=name; this.tall=tall; this.toSleep=function(){ alert('no sleep' ...
- 伪Acmer的推理(dfs/bfs)
时间限制:1000MS 内存限制:65535K 提交次数:12 通过次数:9 收入:32 题型: 编程题 语言: C++;C Description 现在正是期末,在复习离散数学的Acmer遇到 ...
- MFC CString to char* (Visual Studio 2015 亲测可用)
右键划线部分,打开属性,然后找到:配置属性-常规-字符集,选择:使用多字节字符集 然后,char *c;CString str; 就可以 strcpy(c,str); 如果觉得好用,请点个赞,谢谢!
- 洛谷 P1379 八数码难题 Label:判重&&bfs
特别声明:紫书上抄来的代码,详见P198 题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给 ...
- Jquery表格变色 复选框全选,反选
/*jquery静态表格变色*/ $(".tr2").mouseover(function(){ $(this).css("background"," ...
- c 语言结构体的三种定义方式
struct 结构体名{ 成员列表: ..... }结构体变量: 结构体类型变量的定义 结构体类型变量的定义与其它类型的变量的定义是一样的,但由于结构体类型需要针对问题事先自行定义,所以结构体 ...