HAVING用于对GROUP BY分组后的结果进行筛选,作用于聚合数据,不能替代WHERE;WHERE在分组前执行且无法使用COUNT()等聚合函数,而HAVING紧跟GROUP BY后,支持聚合条件过滤。

在 MySQL 中,HAVING 用于对 GROUP BY 分组后的结果 进行条件筛选,它作用于聚合后的数据,不能替代 WHERE(WHERE 是在分组前过滤原始行)。
为什么不能用 WHERE 筛选分组结果
WHERE 在 GROUP BY 之前执行,无法访问聚合函数(如 COUNT()、SUM()、AVG())的结果。比如你想查“订单数超过 5 的客户”,COUNT(*) 是分组后才有的值,WHERE 无法使用它。
错误写法:
SELECT customer_id, COUNT(*) FROM orders WHERE COUNT(*) > 5 GROUP BY customer_id;
会报错:WHERE 不允许使用聚合函数。
HAVING 的基本写法和位置
HAVING 必须紧跟在 GROUP BY 之后,语法结构为:
SELECT 列名, 聚合函数
FROM 表名
GROUP BY 分组列
HAVING 过滤条件;
例如,查下单次数 ≥ 3 的客户及其订单数:
SELECT customer_id, COUNT(*) AS order_count
FROM orders
GROUP BY customer_id
HAVING COUNT(*) >= 3;
常见实用场景与写法
✔️ 筛选满足聚合条件的分组
- 平均金额高于 1000 的产品类别:
HAVING AVG(price) > 1000 - 总销量超过 1000 且订单数不少于 20 的销售员:
HAVING SUM(quantity) > 1000 AND COUNT(*) >= 20
✔️ 结合别名简化 HAVING 条件(MySQL 支持)
可以给聚合结果起别名,在 HAVING 中直接引用(注意:标准 SQL 不保证支持,但 MySQL 允许):
SELECT department, AVG(salary) AS avg_sal
FROM employees
GROUP BY department
HAVING avg_sal > 8000;
WHERE 和 HAVING 混用的顺序逻辑
完整执行顺序是:
WHERE → GROUP BY → HAVING → ORDER BY → LIMIT
这意味着:
- WHERE 先过滤掉不需要参与分组的原始记录(如只统计“已支付”订单)
- HAVING 再从分组结果中筛出符合条件的组(如“该客户已支付订单数 ≥ 2”)
典型组合示例:
SELECT customer_id, COUNT(*) AS paid_orders
FROM orders
WHERE status = 'paid' -- 先筛出已支付的原始订单
GROUP BY customer_id
HAVING COUNT(*) >= 2; -- 再筛出至少 2 笔已支付订单的客户










