HAVING的使用
HAVING的作用:
HAVING是用来过滤数据的
下面我们通过一个例子来理解having的使用
- 首先我们先来一个错误的写法
SELECT department_id,MAX(salary)
FROM employees
WHERE MAX(salary)>10000
GROUP BY department_id;
- 这种写法是错误的,因为WHERE过滤条件中不能出现聚合函数,如果过滤条件中出现聚合函数,则必须使用having进行条件的过滤
那么为什么WHERE过滤条件中不能出现聚合函数?
因为聚合函数是在分组的基础上执行的,如果我们都还没有分组,那么聚合函数是无法执行的,也就是我们要执行了group by操作之后才可以在后面的操作中使用到聚合函数(分组函数),然后很不幸的是,WHERE的执行在group by的前面,所以在where子句中不能出现聚合函数 — 所以我们就提出了having,having的执行是在group by之后的,所以我们就可以使用having关键字对分组后的数据进行分组
- 那么有的人又会询问: — 如果一个查询语句中没有分组操作呐?这个时候不分组难道就不能使用聚合函数
- 不是的,如果一个插叙语句中没有使用到group by操作,但是这个时候也得是按照sql语句执行的顺序执行,一直到执行到按理来说group by应该出现的位置,这个时候如果应该出现group by操作的位置没有出现group by操作,那么系统会默认将所有的数据装到一起分为一个大组
- 那么有的人又会问: 那既然没有group by操作,我们为什么不一开始就分成一个大组?
- 因为电脑是死的,他一开始并不会知道sql语句中有没有group by操作,只有当我们的sql执行到应该出现group by操作的时候,这个时候没有出现,那么我们的机器才知道没有执行分组操作,这个时候就会将我们的所有数据分为一个大组
所以综上,上面的例题的正确写法就要用到having关键字,正确写法如下:
SELECT department_id,MAX(salary)
FROM employees
GROUP BY department_id
HAVING MAX(salary)>10000;
- 这个时候就是正确的写法: 也就是我们一旦过滤条件中出现分组函数(聚合函数),那么我们就要使用having关键字来过滤
那么有的人可能会有疑问: 如果我们没有group by分组操作,我们还可以使用having进行过滤操作吗?
首先是肯定可以的,因为没有group by操作的时候,这个时候其实就是在执行到group by应该出现的位置时将表中的数据都分为了一个大组,所以我们即使没有使用group by显式的进行分组操作,我们也还是可以使用having关键字进行数据过滤
- 但是如果我们没有显示的执行group by操作,这个时候我们使用having语句就是多余的,因为我们的having关键字就是来对分组后的数据进行过滤筛选的,这个时候如果我们没有执行分组操作,也就是没有执行group by操作,那么就是分成了一个大组,那么我们还筛选什么? ---- 只有一个组了,我们就不需要筛选了 , 如果是由分组操作,也就是有group by操作的时候,如果我们这个时候是将表中的数据分成了100个组,那么这个时候我们使用having对分组后的数据进行筛选,这个时候就是从这100个组中进行筛选,选出最终结果
总结: 对于没有group by操作,但是加having关键字也肯定可以的,但是实际开发中不会有这种需求,所以我们说: “在开发中,我们使用having的前提就是使用了group by”
那么WHERE和HAVING有什么区别?我们再开发中如何选择?
这里我们通过一个例题来说明: 问题: 查询部门id为10,20,30,这三个部门中最高工资比10000高的部门信息
- 这里我们有两个方式解决这一问题
方式一:
SELECT department_id,MAX(salary)
FROM employees
WHERE department_id IN(10,20,30)
GROUP BY department_id
HAVING MAX(salary) > 10000;
- 这个时候就是将含有聚合函数的判断条件放到了having中,将不含有聚合函数的判断条件放到了where中
方式二:
SELECT department_id,MAX(salary)
FROM employees
GROUP BY department_id
HAVING MAX(salary) > 10000 AND department_id IN(10,20,30);
- 这个时候就是将含有聚合函数的判断条件和不含有聚合函数的判断条件都放到了having中去,这个时候我们执行之后发现程序还是可以正常执行,并且程序的执行结果也是正确的
- 但是在这个方式二中我们可以发现: 即使是没有聚合函数的筛选操作也可以放到having中去做,那么这样难道不是having关键字把where关键字所做的事情也做了?
- 这里的确可以说:是也不是,having是可以把where的事情做了,但是使用having关键字的效率没有使用where高
- 为什么使用having关键字的效率没有where高?
- 我们通过一个例子说明: 假如我们的表中有10万条记录,这个时候我们如果是将不含分组函数的筛选条件写到了where中,将含有聚合函数的筛选条件写到了having中,这个时候我们按照sql语句的执行顺序,就会先执行where,这个时候经过where一筛选之后我们发现表中剩下了10条记录了,然后再通过group by操作之后分成了三个组,然后再执行having操作,对这三个组进行下一步的筛选,假如这个时候最终筛选出的结果只有一个 ---- 但是如果这个时候是使用的方式二的方式进行查询,也就是将含有分组函数和不含有分组函数的筛选条件都放到了having中,这个时候假如还是10万条记录,这里由于我们没有使用where,而是将where做的事情写到了having中,那么这个时候我们就是直接对这10万条记录进行了分组,假如这个时候分成了1万组,然后我们又要对这1万组进行having操作,这个时候筛选出来的结果肯定是正确的,也就是还是最终值选择出了一组,也就是只筛选出了一条记录
- 通过上述的说明: 我们能明显感觉到使用where的效率要比使用having高,因为使用where是在分组前进行筛选,而使用having是对分组后的数据进行筛选,而越早进行筛选的效率越高
总结:(where 与 having的对比)
- 从适用范围上来讲: HAVING的使用范围更广
- 如果过滤条件中没有聚合函数,这种情况下,where的执行效率高于having(因为where是先筛选后分组的,而having是先分组后筛选的)