MYSQL: having , where 的区别与联系

目录

having的使用

区别

合并使用

HAVING后面需要使用聚合函数

去重的效率对比:(distinct + where)vs(group by + having)

sql语句的执行顺序会变化——mysql优化器

1054报错


having的使用

having :

step1:我们要把所有的信息都准备好,包括从关联表中获取需要的信息,

step2: 对数据集进行分组,形成一个包含所有需要的信息的数据集合。

step3: 接着,再通过 HAVING 条件的筛选,得到需要的数据

区别

区别1: 在关联查询中,WHERE 比 HAVING 更高效。

如果需要通过连接从关联表中获取需要的数据,WHERE 是先筛选后连接,HAVING 是先连接后筛选。

因此,在关联查询中,WHERE 比 HAVING 更高效。

因为,

  • WHERE 可以先筛选,用一个筛选后的较小数据集和关联表进行连接,这样占用的资源比较少,执行效率也就比较高。

  • HAVING 则需要先把结果集准备好,也就是用未被筛选的数据集进行关联,然后对这个大的数据集进行筛选,这样占用的资源就比较多,执行效率也较低。

区别2: 需要进行分组统计的时候,HAVING 可以完成 WHERE 不能完成的任务。

  • WHERE 可以直接使用表中的字段作为筛选条件,但不能使用分组中的计算函数作为筛选条件;

  • HAVING 必须要与 GROUP BY 配合使用,可以把分组计算的函数和分组字段作为筛选条件。

因此,在需要对数据进行分组统计的时候,HAVING 可以完成 WHERE 不能完成的任务。

这是因为,在查询语法结构中:

  • WHERE 在 GROUP BY 之前,所以无法对分组结果进行筛选。(硬要进行分组查询的话,可能需要好几步,并把中间结果存储起来,再使用where进行筛选,或者干脆把这部分筛选功能放在应用层面,用代码来实现。但是,这样做的效率很低,而且会增加工作量,加大维护成本。所以,学会使用 HAVING,对你完成复杂的查询任务非常有帮助。)

  • HAVING 在 GROUP BY 之后,可以使用分组字段和分组中的计算函数,对分组的结果集进行筛选,这个功能是 WHERE 无法完成的。

合并使用

需要注意的是,WHERE 和 HAVING 也不是互相排斥的,我们可以在一个查询里面同时使用 WHERE 和 HAVING。

我们可以把条件拆分开,

  • 包含分组统计函数的条件用 HAVING,

  • 普通条件用 WHERE。

这样,我们就既利用了 WHERE 条件的高效快速,又发挥了 HAVING 可以使用包含分组统计函数的查询条件的优点。 当数据量特别大的时候,运行效率会有很大的差别。

HAVING后面需要使用聚合函数

Q:用 HAVING 查询单笔超过 50 元商品的 SQL 中,用到了 HAVING max(a.salesvalue)>50这个 max() 我不太理解,是指在分组后对每个组中的 salesvalue 取最大值再和 50 比较吗? 这块不明白导致后面原文说的“第三步,对分组后的数据集进行筛选,把组中字段“salesvalue”的最大值 >50 的组筛选出来。”就更不明白了。 我的疑问是,需求是找到比 50 大的就好,不理解这里为什么用到求最大值。求的是哪些数据范围的最大值呢?

A1:作者回复: 这里用max()的主要目的是,消除结果集中的重复记录。获得正确结果的方法不止一种,文中的查询主要是为了演示HAVING()的用法。

A2: 我的回复:我尝试了不加max 直接 having a.salesvalue>50, 会报错 1055。搜了一下,说是having后面要跟聚合函数——因为——having 的功能本来就是对 group by 分组后的数据进行第二次筛选的,所以 只能是一个聚合函数,否则会产生1对n的错误

A3:作者回复:HAVING后面的条件,必须是包含分组中计算函数的条件。这种说法是有道理的,主要是考虑到查询的效率。因为如果不是分组中的计算函数的条件,那么这个条件应该可以用WHERE而不是用HAVING,查询的效率就不高了


去重的效率对比:(distinct + where)vs(group by + having)

Q2: ===>MySQL distinct 与 group by 去重(where/having) - 李留广 - 博客园去重可以使用distinct,或者group by,两者效率如何对比?

  1. 联系前面的distinct,只是为了防止重复的话也可以用DISTINCT来替代。

  2. 那么想到了执行效率问题。搜到一篇文章(MySQL distinct 与 group by 去重(where/having) - 李留广 - 博客园) 说group by比distinct效率高一些。

  3. 但是在这个示例中 是用的(distinct +where) vs (group by+having ),where又比group by效率高一些,那么该如何判断这两个方案的效率呢?类似情况该依赖什么依据进行选择呢?

下面是两个方案的代码:

方案1 :distinct+where

select DISTINCT b.goodsname
from transactiondetails as a
join goodsmaster as b
on a.itemnumber = b.itemnumber
where a.salesvalue>50;

方案2 group by

select b.goodsname
from transactiondetails as a
join goodsmaster as b
on a.itemnumber = b.itemnumber
group by b.goodsname
having max(a.salesvalue)>50;
​

sql语句的执行顺序会变化——mysql优化器

Q:sql语句的执行顺序,不是先执行join 再执行where吗?老师在提到where优点的时候说where的优点是先筛选在关联。这里似乎跟sql执行的顺序有了矛盾呢

A: 作者回复: mysql优化器在制定查询计划的时候,会对查询进行优化,比如重写查询语句,目的是提高查询的速度效率,不会机械按照固定的顺序执行。


1054报错

操作上来说: select 后面的字段如果不在group by分组内,会报错only_full_group_by的错,可以通过SELECT @@GLOBAL.sql_mode;查看全局参数,然后把only_full_group_by去掉,这样sql就不会报错了,但是还需要考虑这样执行出来的结果,是否正确。

业务逻辑上来说:既然分组,自然就会只用到分组字段和组内的计算,如果你还要用到其他字段,应该是你这个查询的需求还没有分析好。

猜你喜欢

转载自blog.csdn.net/lamanchas/article/details/121404866