理解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.)联合使用来得到一个或多个列 ...
随机推荐
- eclipse文本域内只能输入繁体中文
背景:在文本编辑器下写纯文本时不知怎么回事儿,原来能输入简体字,但过了之后只能输入繁体中文了!我用的是sogou拼音输入法,我检查过,输入法设置的是简体中文,eclipse默认的编码方式是utf-8. ...
- loadrunner写入数据到文件
首先在F盘创建: F:\\LR\\test.txt文件 #define USERCOUNT 100 //定义参数数量 Action() { char *namecommon=" ...
- 指针数组 vs 数组指针
指针数组,故名思义,就是指针的数组,数组的元素是指针: 数组指针,同样,就是直想数组的指针. 简单举例说明: int *p[2]; 首先声明了一个数组,数组的元素是in ...
- javascript关键字和保留字
1 关键字breakcasecatchcontinuedefaultdeletedoelsefinallyforfunctionifininstanceofnewreturnswitchthisthr ...
- delphi中VirtualStringTree树使用方法之终结篇!
VirtualStringTree 的用法详解:作者:张志宝go淘宝 例子:创建了一个树名为VirtualStringTree1,第一列显示数据库字段ID的值,标题为编号:第二列显示字段Name的值, ...
- jQuery跨域
其实jQuery跨域很简单很简单,你记住格式就好,跨域的原理请参考 <jsonp跨域> jQuery跨域代码: $.ajax({ url:'https://suggest.taobao.c ...
- The 13th Zhejiang Provincial Collegiate Contest(2016年浙江省赛)
前4道水题就不说了,其中我做了C题,1Y,小心仔细写代码并且提交之前得确认无误后提交才能减少出错率. 结果后面2题都由波神做掉,学长带我们飞~ 终榜 官方题解 ZOJ 3946 Highway ...
- The name does not exist in the namespace error in XAML
方法1:In the solution property page, check the platform of the assembly that contains "UpdatingMe ...
- mac mysql
http://blog.neten.de/posts/2014/01/27/install-mysql-using-homebrew/
- ural 1069. Prufer Code
1069. Prufer Code Time limit: 0.25 secondMemory limit: 8 MB A tree (i.e. a connected graph without c ...