You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQL中WHERE与HAVING筛选聚合结果的差异及疑问

WHERE与HAVING子句的筛选差异解析

我需要按每个客户(id)和订单日期的组合,找出金额在50美元至200美元范围内的最大订单金额。但使用分别带WHERE和HAVING子句的两个SQL查询后,得到的结果不同,且预期结果为HAVING子句查询的结果,希望理清两者的筛选差异及原因。

查询1(WHERE子句)

SELECT id, order_date, MAX(price)
FROM orders
WHERE price BETWEEN 50 AND 200
GROUP BY id;

查询1结果

id  order_date  MAX(price)
1   2013-01-10  103.50
5   2013-01-01  195.50
6   2013-01-01  172.50
8   2013-01-01  147.20
9   2013-01-01  165.60
10  2013-01-01  184.00
12  2013-01-18  191.40
24  2013-01-02  138.00
25  2013-01-07  100.63
26  2013-01-16  86.71
30  2013-01-03  155.25
35  2013-01-08  96.60
36  2013-01-02  169.74
40  2013-01-03  197.80
45  2013-01-02  124.20
48  2013-01-02  149.04
50  2013-01-03  157.55
52  2013-01-03  173.42
60  2013-01-03  186.30
75  2013-01-02  181.13
100 2013-01-04  147.20
125 2013-01-04  184.00

查询2(HAVING子句)

SELECT id, order_date, MAX(price)
FROM orders
GROUP BY id
HAVING MAX(price) BETWEEN 50 AND 200

查询2结果

id  order_date  MAX(price)
25  2013-01-03  100.63
26  2013-01-16  86.71
35  2013-01-08  96.60
45  2013-01-02  124.20
52  2013-01-03  173.42

核心差异与原因分析

1. 执行时机不同

  • WHERE子句:在分组(GROUP BY)前执行。它先过滤掉所有price不在50-200范围内的行,再对剩余行按id分组计算最大金额。也就是说,只要客户有至少一笔订单金额符合50-200的条件,就会进入结果(比如id=1的客户,即便有超过200的订单,只要存在符合条件的订单,就会被保留并计算该范围内的最大金额)。
  • HAVING子句:在分组后执行。它先对所有订单按id分组,计算每个客户的所有订单中的最大金额,再过滤掉最大金额不在50-200范围内的分组。只有那些客户的所有订单里,最大金额本身就在50-200区间的分组才会被保留。

2. 筛选对象不同

  • WHERE针对单个行的price值进行筛选,只要某行数据符合条件就会进入后续分组流程。
  • HAVING针对分组后的聚合结果(这里是MAX(price))进行筛选,只有整个分组的聚合值满足条件,该分组才会出现在最终结果中。

3. 额外注意:GROUP BY与SELECT列的不匹配

两个查询中SELECT包含order_date,但GROUP BY仅按id分组,这种写法不符合SQL标准(仅部分数据库如MySQL的非严格模式允许),返回的order_date是该id对应的任意一条订单日期,结果不可靠。如果你的需求是按id和订单日期的组合分组,正确的写法应该是GROUP BY id, order_date。


内容的提问来源于stack exchange,提问作者Lilly_Co

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 05:01:41