HAVING 子句

最近更新时间:2026-05-06 16:28:13

我的收藏
HAVING 子句用于对 SELECT 查询的汇总结果进行过滤。与 WHERE 子句在分组前过滤单条记录不同,HAVING 是在数据分组及聚合计算完成后,对“组”级别的数据进行筛选。

核心特性

聚合依赖:主要用于检查聚合函数(如 COUNT()SUM()AVG()MIN()MAX())的结果。
分组配合:通常与 GROUP BY 子句结合使用。
支持子查询:HAVING 条件中可以嵌入标量子查询,实现动态过滤。

HAVING 与 WHERE 对比

特性
WHERE 子句
HAVING 子句
执行阶段
在分组前(GROUP BY 之前)执行
在分组后(GROUP BY 之后)执行
作用对象
原始表中的每一行记录
聚合后的每一个分组(Group)
支持函数
不支持聚合函数
专门处理聚合函数

代码示例

基础用法:筛选特定规模的分组

统计各类别下的记录数,并仅保留记录数超过 1 条的类别:
SELECT category, COUNT(*) AS cnt
FROM t1
GROUP BY category
HAVING cnt > 1;

结合标量子查询

HAVING 子句可以根据其他查询返回的单一数值进行过滤。

示例 1:静态标量子查询对比

-- 筛选记录数大于子查询指定值(此处为 1)的分组
SELECT category, COUNT(*) AS cnt
FROM t1
GROUP BY category
HAVING COUNT(*) > (SELECT 1);

示例 2:使用聚合函数子查询实现动态过滤

-- 查找类别编号(或数值)大于全局平均类别的分组
SELECT category, COUNT(*) AS cnt
FROM t1
GROUP BY category
HAVING category > (SELECT avg(category) from t1);

结合标量子查询

-- HAVING 子句中使用标量子查询
SELECT category, COUNT(*) AS cnt
FROM t1
GROUP BY category
HAVING COUNT(*) > (SELECT 1);

-- 使用聚合函数作为子查询
SELECT category, COUNT(*) AS cnt
FROM t1
GROUP BY category
HAVING category > (SELECT avg(category) from t1);

优化建议与注意事项

性能原则:如果过滤条件不涉及聚合函数(例如 WHERE status = 'Active'),请务必将其写在 WHERE 子句中。这样可以在分组计算前排除无关数据,显著提升查询效率。
别名引用:HAVING 可以直接引用 SELECT 列表中的列别名(如示例中的 cnt),这增加了代码的可读性。