having 和 where 的区别
having和where均用于 “过滤数据”,核心区别在于 “过滤时机” 和 “作用对象”,具体对比如下:
# 1. 核心区别
| 对比维度 | where | having |
|---|---|---|
| 过滤时机 | 分组前过滤(过滤行数据) | 分组后过滤(过滤分组结果) |
| 作用对象 | 行数据(如WHERE age > 20过滤年龄大于 20 的行) | 分组结果(如HAVING COUNT(*) > 2过滤包含 2 行以上的分组) |
| 支持的表达式 | 只能使用表字段、常量、函数(不能使用聚合函数,如 COUNT、SUM) | 可使用表字段、常量、函数、聚合函数 |
| 适用场景 | 单表过滤、多表关联过滤(分组前的数据过滤) | 分组后的结果过滤(如 GROUP BY 后的统计过滤) |
# 2. 语法示例与结果对比
# 测试数据:
CREATE TABLE user (id INT, name VARCHAR(20), age INT, dept VARCHAR(20));
INSERT INTO user VALUES
(1, '张三', 25, '技术部'), (2, '李四', 30, '技术部'),
(3, '王五', 28, '销售部'), (4, '赵六', 22, '销售部'),
(5, '孙七', 35, '技术部');
1
2
3
4
5
2
3
4
5
# (1)where 示例(分组前过滤)
需求:查询技术部年龄大于 25 的用户。
SELECT * FROM user WHERE dept = '技术部' AND age > 25;
1
# 结果(过滤出技术部且年龄 > 25 的行):
| id | name | age | dept |
|---|---|---|---|
| 2 | 李四 | 30 | 技术部 |
| 5 | 孙七 | 35 | 技术部 |
# (2)having 示例(分组后过滤)
需求:查询员工人数大于 2 的部门及其人数。
SELECT dept, COUNT(*) AS user_count FROM user
GROUP BY dept -- 按部门分组
HAVING COUNT(*) > 2; -- 过滤人数大于2的分组
1
2
3
2
3
# 结果(过滤出人数 > 2 的分组):
| dept | user_count |
|---|---|
| 技术部 | 3 |
# 3. 关键注意事项
- having 不能单独使用:having 必须与 GROUP BY 配合使用(MySQL 允许不写 GROUP BY,但不推荐,此时 having 等价于 where);
- 聚合函数的使用:where 中不能使用聚合函数(如
WHERE COUNT(*) > 2是错误的),having 中可以; - 性能优化:过滤数据时,优先使用 where(分组前过滤,减少分组的数据量),再用 having 过滤分组结果(如
WHERE dept = '技术部' GROUP BY dept HAVING COUNT(*) > 2,先过滤技术部,再分组统计)。
上次更新: 12/30/2025