SQL中WHERE与HAVING的区别详解及实战用法

一颗松果
一颗松果
发布时间:2026-10-14 | 5人浏览过
原创

在SQL查询构建中,准确区分 WHERE 和 HAVING 是提升查询效率的关键。二者虽都用于数据过滤,但作用阶段截然不同:WHERE 在分组前筛选单行数据,不能直接使用聚合函数;而 HAVING 在分组后筛选结果集,通常用于处理聚合后的条件判断。

核心差异与工作流

理解这两者区别的最佳方式是将其置于完整的SQL执行逻辑中考察。一条包含过滤逻辑的查询语句,其执行顺序决定了数据何时被拦截:

  1. FROM & JOIN:确定数据源。
  2. WHERE:对原始数据进行逐行过滤(此时尚未分组)。
  3. GROUP BY:将筛选后的数据进行归类聚合。
  4. HAVING:对聚合后的各组数据进行筛选。
  5. SELECT:输出最终列。

第1步:使用 WHERE 进行基础过滤

目的:减少进入分组计算的数据量,从而提升性能。
规则:作用于表或视图的行级别。可以使用任意列名进行比较。
禁忌:因为此时数据尚未分组,所以 WHERE 内部绝对不能包含 COUNT(), SUM(), AVG() 等聚合函数。

典型场景:筛选出薪资大于5000的员工记录。

SELECT department, COUNT(*) 
FROM employees 
WHERE salary > 5000;
-- 这里先过滤掉低薪员工,剩下的再按部门统计

第2步:使用 HAVING 进行分组后筛选

目的:在统计完成之后,剔除不符合特定“整体”条件的组。
规则:作用于 GROUP BY 产生的结果集(即“组”)。
特点:专门配合聚合函数使用,例如“筛选出员工总数超过10人的部门”。

SELECT department, COUNT(*) as emp_count
FROM employees 
WHERE salary > 5000 
GROUP BY department
HAVING COUNT(*) > 5;
-- 统计出人数大于5人的高薪员工部门

常见误区与最佳实践

很多初学者容易混淆两者的位置。有一个直观的类比记忆法:

  • WHERE 像是在进考场前先查身份证(筛选人)。
  • HAVING 像是查分后筛选不及格的班级(筛选分组结果)。

为什么不建议滥用 HAVING?

如果过滤条件不涉及聚合函数(如 SELECT * FROM table HAVING id > 1),虽然语法上可能允许某些数据库执行,但属于极低效的做法。原因如下:

  1. 性能损耗:使用 HAVING 往往意味着必须先执行全表扫描并进行分组聚合,最后才做筛选;而 WHERE 可以在读取数据时直接丢弃不匹配的行,大幅减轻后续步骤的压力。
  2. 可读性:违背常规逻辑,增加维护成本。

综合应用示例

假设我们有一张订单表 orders,要求查询出:2023年以后创建的、且平均订单金额超过100元的客户ID。

我们需要结合两者:利用 WHERE 过滤时间范围以减少数据量,利用 HAVING 过滤平均值高的用户组。

SELECT customer_id, AVG(amount) as avg_amount
FROM orders
WHERE created_at >= '2023-01-01'  -- WHERE: 先过滤掉旧年份订单
GROUP BY customer_id              -- GROUP BY: 按客户分组
HAVING AVG(amount) > 100          -- HAVING: 再过滤掉均值不够的客户组

总结

掌握 WHERE 与 HAVING 的本质区别,关键在于把握“时间线”。凡是能用 WHERE 提前拦截的条件,绝不留给 HAVING;只有涉及“统计后的结果”(如总数、平均值、最大值比较),才必须移动到 HAVING 中进行判断。这种搭配不仅能确保逻辑正确,更是写出高性能 SQL 的基础规范。

以上就是SQL语句中where和having的区别的详细内容,更多关于SQL过滤与优化的资料请关注本站其它相关文章!

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表