跳转到主要内容
模块 3 · 第 4 课(共 4)课程中的12/57~8 min
模块课程(4/4)

过滤组:HAVING

一旦您获得了每组的结果(上一课),您通常会想要 仅保留满足条件的组:拥有更多的部门 2人以上,项目平均预算10万以上,用户 至少 10 个订单。要做到这一点 WHERE 还不够。

为什么 WHERE 还不够

WHERE 过滤 表行,before 聚合。所以看不到 COUNT(*) 或 AVG(...) 的结果:到 WHERE 运行时,那些 值尚未计算。

SQL
-- ERROR: COUNT(*) doesn't exist yet when WHERE is evaluated
SELECT department_id, COUNT(*) AS count
FROM   employees
WHERE  COUNT(*) > 2     -- ❌ doesn't work
GROUP BY department_id;

要在聚合后过滤,有一个专用子句:HAVING。

语法

SQL
SELECT grouping_column, AGGREGATE_FUNCTION(...)
FROM   table
GROUP BY grouping_column
HAVING   condition_on_aggregate;
SQL
-- Departments with more than 2 employees:
SELECT department_id, COUNT(*) AS count
FROM   employees
GROUP BY department_id
HAVING   COUNT(*) > 2;

HAVING 与 GROUP BY 的关系就像 WHERE 与 FROM 的关系:相同的想法 (“过滤器”),但在聚合之后应用**分组。

子句的逻辑顺序

为了不再混淆 WHERE 和 HAVING,请记住其中的顺序 SQL 在心里执行它们:

  1. FROM / JOIN — 通过连接源构建起始表。
  2. WHERE — 删除您不关心的行。
  3. GROUP BY — 将剩余行收集到组中。
  4. HAVING — 删除您不关心的组。
  5. SELECT — 计算最终列(包括聚合)。
  6. ORDER BY / LIMIT — 重新排序和剪切。

重要提示:

  • 在WHERE中你只能使用表列;
  • 在 HAVING 中,您可以使用分组列和聚合。
SQL
-- Classic combo: filter first, group, filter the groups, sort.
SELECT d.name, AVG(e.salary) AS average
FROM   employees   AS e
JOIN   departments AS d ON e.department_id = d.id
WHERE  e.hired_on >= '2018-01-01'   -- filter rows
GROUP BY d.name
HAVING   AVG(e.salary) > 35000      -- filter groups
ORDER BY average DESC;

尝试一下

锻炼#sql.m3.l4.e1
尝试:0加载中...

对于每个部门,显示名称 (departments.name) 和员工人数,但仅适用于至少有 2 名员工的部门。每个合格部门两列,一行。

正在加载编辑器...
显示提示

“至少 2”条件在 HAVING 中变为 COUNT(*) >= 2。

3 次尝试后可用的解决方案

复习练习

锻炼#sql.m3.l4.e2
尝试:0加载中...

显示平均工资超过 35000 的部门 (departments.name)。仅考虑从 2018 年起雇用的员工。两列:名称和平均值。按平均降序排序。

正在加载编辑器...
显示提示

WHERE 过滤行(从 2018 年开始雇用的员工),HAVING 过滤组(平均值 > 35000)。

3 次尝试后可用的解决方案