GROUP BY 将共享一个值的行分组,以便聚合函数对每个组进行计算。HAVING 过滤这些组(类似 WHERE,但用于组/聚合)。它们一起构成了按类别汇总和分析数据的核心。
GROUP BY — 每组聚合
sql
country, () user_count, (age) avg_age
users
country;
GROUP BY 将共享一个值的行分组,以便聚合函数对每个组进行计算。HAVING 过滤这些组(类似 WHERE,但用于组/聚合)。它们一起构成了按类别汇总和分析数据的核心。
country, () user_count, (age) avg_age
users
country;
GROUP BY country 将每个国家的所有行折叠到一个组中,聚合函数(COUNT、AVG)为每个组计算一个值。你可以按多列分组:
GROUP BY country, city -- a group per unique (country, city) combination
-- show only countries with MORE THAN 100 users
SELECT country, COUNT(*) AS user_count
FROM users
GROUP BY country
HAVING COUNT(*) > 100; -- filter on the AGGREGATE
HAVING 在分组之后对聚合值进行过滤 — WHERE 无法做到这一点(WHERE 在分组前过滤单个行)。
SELECT country, COUNT(*) AS cnt
FROM users
WHERE active = true -- WHERE: filter ROWS first (before grouping)
GROUP BY country
HAVING COUNT(*) > 100; -- HAVING: filter GROUPS after (on aggregates)
WHERE → filters individual ROWS, runs BEFORE grouping, can't use aggregates
HAVING → filters GROUPS, runs AFTER grouping, used WITH aggregates
→ Use WHERE to filter rows, HAVING to filter aggregated groups. (Filter with WHERE
first when possible — it's more efficient, reducing rows before grouping.)
FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY
(WHERE before grouping, HAVING after — which is why their roles differ)
GROUP BY 和 HAVING 是分析型 SQL 的核心 — 按类别汇总和分析数据是一个基础的、持续的需求(每个地区的计数、每个产品的销售额、每个组的平均值),因此理解它们至关重要。GROUP BY(对行进行分组,以便聚合按组计算)是这些汇总查询的基础,理解它如何为聚合将行折叠成组是任何报告或分析的必要条件。
WHERE 与 HAVING 的区别特别重要且容易混淆:WHERE 在分组之前过滤单个行(且不能使用聚合),而 HAVING 在分组之后过滤组(基于聚合值)— 使用错误会导致错误或错误的结果,理解何时应用每一个(WHERE 用于行级过滤,HAVING 用于组的聚合级过滤)是一项关键技能。
知道尽可能先用 WHERE 过滤(更高效 — 在分组前减少行数)是一个有用的优化。
与执行顺序的联系(分组前是 WHERE,分组后是 HAVING)解释了为什么它们的角色不同。
由于分组和聚合过滤在报告和数据分析中无处不在,且 WHERE-vs-HAVING 的区别对正确性既很重要又容易被误解,掌握 GROUP BY 和 HAVING — 用于按类别聚合的分组和两级过滤模型 — 是核心的、经常应用的知识,对分析型 SQL 至关重要,也是常见的面试题目。