SQL Interview Prep · 课时

不使用 GROUP BY 的汇总

了解单独使用汇总函数如何将整张表压缩为一行

第 4 / 4 课13 个步骤

不使用 GROUP BY 的汇总 是 CoddyKit 上的免费 SQL Interview Prep 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 SQL Interview Prep 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 SQL Interview Prep 课程共包含 4 节课。

一个聚合函数,一行

面试官会用这个问题考查一个基础概念:“不使用 GROUP BY 时使用聚合函数会发生什么?”

答案是:整个表会收缩为一行。聚合函数会把所有符合条件的行视为一个大的隐式组。理解这个“隐式组”模型,可以解释许多后续规则,因此让我们仔细建立这个模型。

隐式单组

当您在没有 GROUP BY 的情况下单独使用聚合函数时,SQL 的行为就好像存在一个包含所有行的组。无论表中有多少行,结果始终恰好是一行——即使表为空也是如此。

因此,SELECT COUNT(*) FROM employees 会返回一行,其中包含一个数字,用于概括整个表。

SELECT COUNT(*) AS total_employees
FROM employees;
-- always returns exactly one row

同时使用多个聚合函数

您可以在一个 SELECT 中列出多个聚合函数。它们都会概括同一个隐式组,因此结果仍然恰好是一行,只是包含多个列。

这是标准的“给我汇总统计信息”查询。四个数字描述的是同一组完整的行。

SELECT
  COUNT(*)     AS num_rows,
  SUM(salary)  AS total_pay,
  AVG(salary)  AS avg_pay,
  MAX(salary)  AS top_pay
FROM employees;

混用错误

这是最常被考查的规则。没有 GROUP BY 时,您不能在同一个 SELECT 中把单独的聚合函数与未聚合列混用。

为什么?聚合函数会生成一行,但普通列有许多值——它应该显示哪一个?这存在歧义,因此标准 SQL 会引发错误。

-- ERROR: name is not aggregated and there is no GROUP BY
SELECT name, MAX(salary)
FROM employees;

为什么会产生歧义

结合我们的表来思考。MAX(salary) 会把所有行收缩为一个值,但 name 在每一行中都有不同的值。单个汇总行无法在一个单元格中容纳五个姓名。

数据库拒绝猜测。这正是 GROUP BY 规则背后的相同原则:每个被选中的列都必须经过聚合,或者属于分组。没有 GROUP BY 时,只允许使用聚合列。

MySQL 的宽松例外

有一个值得特别指出的方言细节:较旧或非严格模式下的 MySQL 会允许这种混用查询,并返回一个任意的姓名——不一定是最高收入者的姓名。

启用 ONLY_FULL_GROUP_BY 的现代 MySQL(现在默认启用)会像其他数据库一样拒绝该查询。提到这一点可以体现您对不同 SQL 方言的了解,但请始终把混用查询视为错误。

获取 MAX 背后的行

那么,如何获取收入最高员工的姓名?不能靠混用。请使用 ORDER BY + LIMIT,或者使用与聚合结果进行比较的子查询。

ORDER BY/LIMIT 版本最简单。子查询版本更容易推广,并且会返回所有并列最高收入的员工。

-- Subquery: returns everyone earning the max
SELECT name, salary
FROM employees
WHERE salary = (SELECT MAX(salary) FROM employees);

空表上的聚合函数

面试官可能会埋下这样的边界情况:“单独使用聚合函数时,空表会返回什么?”

  • COUNT(*) 返回 0(一行,值为 0)。
  • SUM、AVG、MIN、MAX 返回 NULL(一行,值为 NULL)。

关键在于,您仍然会得到一行结果,绝不会得到零行。这种单行保证正是无 GROUP BY 聚合函数的核心特性。

SELECT COUNT(*) AS c, SUM(salary) AS s, MAX(salary) AS m
FROM employees
WHERE 1 = 0;
-- one row: c=0, s=NULL, m=NULL

不能在 WHERE 中使用聚合函数

根据这一模型还可以得出另一条规则:不能把聚合函数放在 WHERE 子句中,因为 WHERE 会在聚合发生之前筛选单独的行。

如果要根据聚合结果进行筛选,应使用 HAVING(配合分组),或者将聚合函数包装在子查询中。按照执行顺序,WHERE 执行得太早,无法看到聚合结果。

-- ERROR: aggregate not allowed in WHERE
-- SELECT * FROM employees WHERE salary > AVG(salary);

-- Correct: compare to the aggregate via subquery
SELECT name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);

单独聚合函数与 GROUP BY 的对比

请这样理解两者的区别:

  • 没有 GROUP BY:一个隐式组 = 整个表 = 恰好一行结果。
  • 使用 GROUP BY 列:列的每个不同值对应一个组 = 每组一行。

单独使用聚合函数,其实就是分组列数为零的 GROUP BY。同一套机制,只是所有行都放进了一个大桶。

-- Whole table: one row
SELECT AVG(salary) FROM employees;

-- Per department: one row each
SELECT department, AVG(salary)
FROM employees
GROUP BY department;

如何解释

一个简洁的回答是:“不使用 GROUP BY 的聚合函数会把整个结果集视为一个隐式组,并且恰好返回一行汇总结果,即使表为空也是如此。您不能同时选择未聚合列,因为该列的值会产生歧义。如果要获取 MAX 或 MIN 背后的行,我会使用带 LIMIT 的 ORDER BY,或者使用与聚合结果进行比较的子查询。”

快速检查

预测输出结构。

回顾

不使用 GROUP BY 时的聚合函数总结:

  • 整个表会变成一个隐式组,因此恰好得到一行结果。
  • 不能把单独的聚合函数与未聚合列混用。
  • 空表:COUNT(*) = 0,其他函数返回 NULL,但仍然返回一行。
  • 聚合函数不能出现在 WHERE 中;请使用子查询或 HAVING。
  • 要获取 MIN/MAX 背后的行,请使用 ORDER BY + LIMIT 或子查询。

聚合函数相关的面试练习到此完成。

免费开始

用 AI 导师学习 SQL — 免费

在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。

课程
30
课程
120

常见问题解答

「不使用 GROUP BY 的汇总」课时是免费的吗?

是的 — 「不使用 GROUP BY 的汇总」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 SQL Interview Prep 课程的其余内容,请升级到 CoddyKit PRO。 SQL Interview Prep 课程共包含 4 节课。

「不使用 GROUP BY 的汇总」这节课中我会学到什么?

了解单独使用汇总函数如何将整张表压缩为一行 你通过在浏览器中直接运行的动手代码来练习 SQL Interview Prep,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 SQL Interview Prep 需要有经验吗?

无需任何先前经验。CoddyKit 上的 SQL Interview Prep 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。

「不使用 GROUP BY 的汇总」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 SQL Interview Prep 课中编写并运行代码吗?

能。每节 SQL Interview Prep 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. COUNT(*)、COUNT(column) 与 COUNT(DISTINCT)
  2. 包含 NULL 的 SUM 和 AVG
  3. MIN、MAX 与非数值汇总
  4. 不使用 GROUP BY 的汇总
← 返回 SQL Interview Prep