1、聚合函数与group by的联系
-
严格意义来说聚合函数也多多少少跟group by分组存在着一些关系,甚至有些教科书上聚合函数有一些其他的名字,分组函数、多行处理函数…
-
其实聚合函数使用时虽然明面上没有使用group by进行分组,但是可以理解为使用group by将所有的数据分为了一组然后在使用聚合函数!
-
二者在sql中的执行顺序:一定是聚合函数在group by之后进行执行!
2、group by的使用
2.1、使用案例一
查询最高工资与查询每个工作岗位的最高工资
查询最高工资
select max(sal) from emp
查询每个工作岗位的最高工资
select max(sal) from emp group by job
这两个问题是不同的:
-
第一个问题可以认为所有人都是同一个岗位然后找出最大值;
-
第二个问题处理顺序应该是先将所有的人按照工作岗位的不同进行分组,然后在每个小组中找出最大值!
2.2、使用案例二
-
之前聚合函数了解到,单独使用的使用忽略NULL,而且输出的字段只有一行且不能加其他字段;
-
group by只能使用用于分组中的字段以及聚合函数。
-- 查询不同工作岗位对应的最高工资,平均工资
select job, max(sal), avg(sal) from emp group by job;
错误使用
select sal, job, max(sal), avg(sal) from emp group by job;
2.3、执行顺序
-
SQL查询是非常强大的,针对不同的SQL语句会有不同的执行顺序,这些顺序都是相对的!
-
首先找到需要查找的表,再执行待执行的where条件;然后进行分组,可能还要对分组的数据进行过滤,然后执行select列出需要查找的字段,最后排序输出!
-
正因为这个执行顺序,因此where条件中不能直接出现聚合函数(子查询中的不算),因为聚合函数需要在groupby执行之后才能执行;而where条件的执行顺序又早于groupby!
select //5
字段
..
from //1
表名
..
where //2
条件
..
group by //3
..
分组
having //4
..
对分组条件过滤
order by //6
..
排序
3、having的使用
-
使用having必须先使用group by,无法单独使用having。
-
having与where都有过滤的意思,只不过having是在group by之后执行,可以看做二次过滤!
-
在同等条件下能使用where过滤的绝对不使用having!迫不得已没有办法的情况下在使用having。
3.1、案例一
找出各工作岗位的最高薪资,并且显示最高薪资大于2000的。
1. 首先按照要求按照工作岗位分组,找出不同工作岗位的最高薪资。
select job, max(sal) from emp group by job
2. 其次再找出大于2000的
select job, max(sal) from emp group by job having max(sal) > 2000
select job, max(sal) from emp where sal > 2000 group by job
-
分析:虽然第一种语句看起来没什么问题,的确能得到正确答案;但是它并不是一条完美的SQL语句。完全可以不使用having过滤也能得到相同的结果!因为最后需要得到的答案是大于2000的,因此小于等于2000工资的工作岗位压根就没戏,可以先将小于等于2000的排除,最后对工资大于2000的进行分组即可!
-
结论:这样做的好处就是在大量数量的情况下,先过滤在分组、与先分组在过滤二者处理的数据量是不同的;前者的性能更好!因此在同等情况下尽量先使用where进行过滤。
3.2、案例二
找出各工作岗位的平均薪资,并且显示平均薪资大于2000的
1. 首先按照要求按照工作岗位分组,找出不同工作岗位的平均薪资。
select job, avg(sal) from emp group by job
2. 其次再找出大于2000的
select job, avg(sal) from emp group by job having avg(sal) > 2000
-- 错误写法,需要严格遵循执行顺序
select job, avg(sal) from emp where avg(sal) > 2000 group by job
分析:首先只有这一种写法,因为只有分组后计算完才知道平均薪资是多少,无法在分组之前确定每个组的平均薪资,因此只能使用having进行过滤!