在 SQL 查询中,WHERE
和 HAVING
都用于对查询结果进行过滤,但它们在使用场景和作用对象上存在明显的区别。
1. WHERE 子句
WHERE
用于过滤原始数据,它作用于从表中提取的记录,对数据在分组之前进行过滤。
特点
WHERE
只能用于过滤表中的原始行,在数据进行分组操作(GROUP BY
)之前执行。WHERE
子句不能用于聚合函数(如SUM()
、COUNT()
、AVG()
等),因为在WHERE
子句执行时,聚合操作尚未发生。- 用于非聚合的条件过滤。
语法
SELECT column1, column2, ...
FROM table_name
WHERE condition;
举例说明
SELECT name, age
FROM employees
WHERE age > 30;
在这个查询中,WHERE
子句过滤所有 age
大于 30 的记录,查询结果将只包含符合条件的行。
2. HAVING 子句
HAVING
子句通常与分组操作(GROUP BY
)一起使用,作用于分组后的数据,对聚合后的结果进行过滤。
特点
HAVING
用于过滤已经分组后的结果。HAVING
支持使用聚合函数(如SUM()
、COUNT()
、AVG()
等),可以针对分组后的聚合结果进行过滤。- 通常和
GROUP BY
搭配使用。
语法
SELECT column1, aggregate_function(column2), ...
FROM table_name
GROUP BY column1
HAVING condition;
举例说明
SELECT department, COUNT(*) AS employee_count
FROM employees
GROUP BY department
HAVING COUNT(*) > 5;
在这个查询中,HAVING
子句过滤那些员工人数大于 5 的部门。这里 COUNT(*) > 5
是对聚合结果的过滤,而不是对原始数据的过滤。
3. WHERE 和 HAVING 的主要区别
特点 | WHERE | HAVING |
---|---|---|
作用阶段 | 在分组前过滤数据 | 在分组后过滤数据 |
适用于聚合函数 | 不能用于聚合函数 | 可以与聚合函数一起使用 |
使用场景 | 用于过滤表中的原始数据 | 用于过滤聚合后的数据 |
语法位置 | 位于 GROUP BY 之前 | 位于 GROUP BY 之后 |
应用示例 | 过滤单行数据,如 WHERE age > 30 | 过滤聚合数据,如 HAVING COUNT(*) > 5 |
4. 综合实例:WHERE 和 HAVING 的联合使用
有时,我们需要同时使用 WHERE
和 HAVING
来分别过滤原始数据和聚合后的结果。
SELECT department, AVG(salary) AS avg_salary
FROM employees
WHERE age > 30 -- 对原始数据进行过滤
GROUP BY department
HAVING AVG(salary) > 50000; -- 对聚合结果进行过滤
WHERE age > 30
:先过滤出年龄大于 30 的员工。HAVING AVG(salary) > 50000
:然后对分组后的结果过滤出平均工资大于 50000 的部门。
5. 总结
WHERE
在分组前过滤数据,不能用于聚合函数。HAVING
在分组后过滤数据,适用于聚合函数。- 两者可以结合使用,先用
WHERE
过滤原始数据,再用HAVING
过滤聚合后的结果。