MySQL中where和having的区别、SQL语句执行顺序
where和having的区别
我们都知道where
后不能使用聚合函数,而having
后既可以接聚合函数也可以接普通条件,那么就会有一个问题:既然where
能做的事having
都可以做到,那么还用where
干啥?
因此我们对where
和having
的区别进行对比:
区别1:where
可以直接使用表中的字段作为筛选条件,但不能使用分组中的计算函数作为筛选条件;having
必须与group by
配合使用,可以把分组计算的函数和分组字段作为筛选条件
这决定了,在需要对数据进行分组统计的时候,having
可以完成where
所不能完成的任务。这是因为:在查询语法结构中,where
在group by
之前,所以无法对分组结构进行筛选。having
在group by
之后,可以使用分组字段和分组中的计算函数对分组的结果集进行筛选,这个功能是where
无法完成的。另外,where
排除的记录不再包含在分组中。
区别2:如果需要通过连接(即多表连接查询)从关联表中获取需要的数据,where
是先筛选后连接,而having
是先连接后筛选
这一点决定了在关联查询中,where
比having
更高效。因为where
可以先筛选数据,用一个筛选后的较小数据集和关联表进行连接,这样占用的资源比较少,因此执行效率也比较高。having
则需要先把结果集准备好,也就是用未被筛选的数据集与关联表进行关联,然后对这个大的数据集进行筛选,这样占用的资源就比较多,执行效率也比较低。
结论:
where
和having
并不是相互排斥的,因此在开发中:
1. 如果只有普通条件则使用where
;
2. 如果只有聚合函数,则使用having
;
3. 如果两者都有,则使用where
筛选普通条件,使用having
筛选带函数的条件;(如需求2中的第一种筛选方式)
SQL语句执行顺序
这里提一下SQL语句的顺序,现在我们通常用的比较多的应该是MySQL5.7及以上版本,他们使用的SQL99语法规则,旧版的规则暂时忽略
# SQL99语法
select 字段|表达式|常量值|函数 (可以使用聚合函数)
from 表名(单表查询)
[from 表1 [inner|left|right|cross|natural] join 表2 on 多表的连接条件]
where 过滤条件 (不可以使用聚合函数)
group by 字段
having 过滤条件 (可以使用聚合函数)
order by 字段 [asc|desc]
limit 起始索引,增量长度
然后我们直接本主题,一条完整的SQL语句的执行顺序如下:
from --> on --> [inner|left|right|cross|natural] join --> where --> group by --> having --> select --> distinct --> order by --> limit
说明:
**1. from
用于确定要查询的数据表
-
如果是多表连接,则需要通过
on
后的条件对多个表进行连接 -
join
将多个表连接起来,其中left
和right
等关键字来确定用户需要使用哪个表作为基准表(因为基准表不同,返回的数据量也不同,不明白左右连接的可以查看MySQL内连接、左连接、右连接、交叉连接、自连接的区别) -
使用
where
后的条件过滤掉不符合需求的数据 -
group by
对上述过滤后的数据进行分组 -
having
对分组后的数据进行二次筛选/过滤
----(上述操作都是对数据从行的维度进行筛选)----
-
select
从筛选完的数据中提取用户需要查询的字段(select
从筛选结果的列的维度上进行筛选) -
distinct
对select
提取的列进行去重 -
order by
对上述结果进行排序 -
limit
对排序后的数据进行分页返回给用户**
从SQL语句的执行顺序也可以看出为什么where
比having
的执行效率高。因为where
在分组之前已经过滤掉了一部分数据,因此将减少数据执行分组时的数据量。
评论区