Mysql —— where 与 having

本文详细解析了SQL中where子句与having子句的本质区别,包括它们的操作对象、执行顺序及应用场景。通过实例展示了where用于分组前过滤,having则在分组后筛选结果集,强调了聚合函数在两者中的不同作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

资料下载入口

本质区别:where 对磁盘上的表进行操作,而having 是对结果集进行操作;

==> where 是在分组前过滤数据,而having 是在分组之后过滤数据;

执行顺序:

 where 、聚合函数和 having 在from 后面的执行顺序(从先到后):where > 聚合函数(sum,avg,count,max,min)> having

举例说明:

目标:筛选出那些销售价格(shop_price)大于1000商品,并且按照商品分类(cat_id)进行分类,只显示出那些商品的平均销售价格低于3000以及所在的商品分类(cat_id):

SELECT cat_id,avg(shop_price) from goods WHERE shop_price>1000 GROUP BY cat_id HAVING avg(shop_price)<2000;

操作顺序:先筛选shop_price>1000;然后按照cat_id分类,接着计算平均值avg(shop_price),最后在结果集中筛选出那些均值小于2000的行

查询结果:

 

注意事项:where后面不能跟聚合函数,因为where的执行顺序大于聚合函数;

原因:

1.where后面接的子句是在对表进行查询前,将不符合where条件的行去掉,即在分组前过滤数据,所以where条件中不能包含聚合函数;

2.having后面接的子句是筛选满足条件的组,即在分组之后过滤数据,所以having条件中经常包含聚合函数,也可以使用having条件显示特定的组;

具体场景讲解:

1.where和having都可以使用的场景:

SELECT goods_name,shop_price FROM goods WHERE shop_price>1000;
SELECT goods_name,shop_price FROM goods HAVING shop_price>1000;

上面的having可以用的前提是我已经筛选出了shop_price字段,在这种情况下和where的效果是等效的,但是如果我没有select goods_price 就会报错!!因为having是从前筛选的字段再筛选,而where是从数据表中原有的字段直接进行的筛选的。

2. 只可以用where,不可以用having的情况

SELECT goods_name,goods_id FROM goods WHERE shop_price;
//报错!!!因为前面并没有筛选出goods_price 字段
SELECT goods_name,goods_id FROM goods HAVING shop_price;

3. 只可以用having,不可以用where情况

查出每种商品类型(cat_id)对应的平均销售价格(shop_price),只反馈那些平均销售价格小于2000的商品分类;

//报错!!因为goods 这张数据表里面没有AVG(shop_price)这个字段
SELECT cat_id ,AVG(shop_price) FROM goods GROUP BY cat_id WHERE AVG(shop_price)<2000;
//依然报错,即使取了新的列名ag!!因为goods 这张数据表里面没有AVG(shop_price)这个字段
SELECT cat_id ,AVG(shop_price) AS ag FROM goods GROUP BY cat_id WHERE ag<2000;
SELECT cat_id ,AVG(shop_price) FROM goods GROUP BY cat_id HAVING AVG(shop_price)<2000;

 

where -having-group练习题:

有如下表及数据
+------+---------+-------+
| name | subject | score |
+------+---------+-------+
| 张三 | 数学    |    90 |
| 张三 | 语文    |    50 |
| 张三 | 地理    |    40 |
| 李四 | 语文    |    55 |
| 李四 | 政治    |    45 |
| 王五 | 政治    |    30 |
+------+---------+-------+

要求:查询出2门及2门以上不及格者的平均成绩

SELECT name,sum(score<60) as gk,AVG(score) FROM result GROUP BY name HAVING gk>=2;

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值