Z
ZHANK
编程在线教程SQL 教程HAVING 过滤分组
分组与聚合

HAVING 过滤分组

理解 WHERE vs HAVING 的区别、分组后过滤

HAVING 过滤分组

WHERE 在分组前过滤行,HAVING 在分组后过滤分组。很多人分不清这两个——记住:WHERE 不能跟聚合函数,HAVING 专门跟聚合函数。

学完本章你将: 掌握 HAVING vs WHERE 的区别、按聚合结果筛选。


HAVING 基本用法

sql
-- 查用户数超过 5 的城市
SELECT city, COUNT(*) AS 人数
FROM users
GROUP BY city
HAVING COUNT(*) > 5;   -- 过滤分组后的结果

-- ❌ 这样不行:
-- WHERE COUNT(*) > 5   -- WHERE 不能用聚合函数!

WHERE vs HAVING 对比

sql
-- WHERE:过滤原始行(分组前)
-- HAVING:过滤聚合结果(分组后)
SELECT city, AVG(age) AS 平均年龄
FROM users
WHERE age > 0              -- ① 先排除年龄为 0 的脏数据
GROUP BY city
HAVING AVG(age) > 30       -- ② 再筛选平均年龄大于 30 的城市
ORDER BY 平均年龄 DESC;     -- ③ 最后排序

WHERE 和 HAVING 都用

sql
-- 北京的 18+ 用户数 > 3 的部门
SELECT department, COUNT(*) AS 人数
FROM users
WHERE city = '北京' AND age >= 18   -- 先筛选行
GROUP BY department
HAVING COUNT(*) > 3                 -- 再筛选组
ORDER BY 人数 DESC;

能用 WHERE 就别用 HAVING

WHERE 利用索引更快,HAVING 在分组之后才执行。能把条件放 WHERE 里就放 WHERE:

sql
-- ✅ 好
SELECT city, COUNT(*) FROM users WHERE age > 18 GROUP BY city;

-- ❌ 不好(WHERE 能做到的别交给 HAVING)
SELECT city, COUNT(*) FROM users GROUP BY city HAVING city != '测试';