0Pricing
SQL Interview Prep · 课时

DISTINCT 与 GROUP BY 的去重比较

了解什么时候应使用 DISTINCT,以及什么时候面试官希望您改用 GROUP BY

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

DISTINCT 的作用

DISTINCT 会移除重复行。面试官重点检查的是:它作用于选出的整行,而不是某一列,因此 SELECT DISTINCT a, b 会按照 (a, b) 这一对值去重。

SELECT DISTINCT department
FROM employees;

DISTINCT 涵盖所有选中的列

当选中多个列时,DISTINCT 会保留每种唯一组合——每个不同的 (department, job_title) 组合保留一行。标准 SQL 没有只对一列去重的方法。

SELECT DISTINCT department, job_title
FROM employees;

GROUP BY 的作用

GROUP BY 会将具有相同键的行合并为每组一行。单独按某列分组时,结果与对该列使用 DISTINCT 相同。

SELECT department
FROM employees
GROUP BY department;
-- equivalent to:
SELECT DISTINCT department
FROM employees;

真正的区别:聚合

那么它们什么时候不同呢?当您需要聚合时。GROUP BY 可以计算每组的 COUNT、SUM 或 AVG,而 DISTINCT 不行。需要唯一行时使用 DISTINCT,需要每组指标时使用 GROUP BY。

SELECT department, COUNT(*) AS headcount
FROM employees
GROUP BY department;

DISTINCT 无法进行分组计数

您不能在 DISTINCT 上附加计数操作。对于“每个部门有多少名员工”这个问题,正确的工具始终是结合 COUNT(*) 使用 GROUP BY,而不是 SELECT DISTINCT。

-- WRONG intent: this errors or returns one total row
-- SELECT DISTINCT department, COUNT(*) FROM employees;

-- RIGHT:
SELECT department, COUNT(*) AS headcount
FROM employees
GROUP BY department;

COUNT(DISTINCT) 结合了两种思想

一种常用组合是:COUNT(DISTINCT col) 会计算每个组中的唯一值数量。这里的 DISTINCT 位于聚合函数内部,用来回答“每个部门有多少个不同的职位名称?”

SELECT department,
       COUNT(DISTINCT job_title) AS distinct_titles
FROM employees
GROUP BY department;

统计总体中的不同值

没有 GROUP BY 时,COUNT(DISTINCT col) 会统计整张表中的唯一值数量,这是回答“我们有多少个不同的部门?”的简洁方法。

SELECT COUNT(DISTINCT department) AS n_departments
FROM employees;

-- equivalently, count the deduped subquery
SELECT COUNT(*)
FROM (SELECT DISTINCT department FROM employees) d;

性能通常没有明显差异

DISTINCT 和 GROUP BY 哪个更快?对于简单去重,两者通常等效——优化器会采用相似的执行计划。请根据意图选择:需要唯一行时使用 DISTINCT,进行聚合时使用 GROUP BY。

DISTINCT 与 NULL

DISTINCT 如何处理 NULL?它会将所有 NULL 视为相等,因此多行 NULL 会合并为一行。GROUP BY 也是如此——NULL 会形成一个单独的组。

-- If manager_id has several NULLs, this returns one NULL row
SELECT DISTINCT manager_id
FROM employees;

Postgres 的 DISTINCT ON(额外内容)

额外提示:Postgres 提供非标准的 DISTINCT ON (expr),结合 ORDER BY 可以为每个键保留第一行。可移植的代码则使用 ROW_NUMBER()。

-- Postgres only: latest order per customer
SELECT DISTINCT ON (customer_id) customer_id, order_id, order_date
FROM orders
ORDER BY customer_id, order_date DESC;

DISTINCT 作用于整个 SELECT,而不是某一列

还有一个陷阱:DISTINCT 作用于整行,因此 SELECT DISTINCT customer_id, order_date 不会为每个客户返回一行。要实现这一点,请使用结合 MAX 的 GROUP BY,或使用窗口函数。

-- Does NOT give one row per customer
SELECT DISTINCT customer_id, order_date FROM orders;

-- One row per customer: latest order date
SELECT customer_id, MAX(order_date) AS last_order
FROM orders
GROUP BY customer_id;

快速检查

选择正确的工具。

回顾

回顾:DISTINCT 对整行去重;GROUP BY 按键合并行并支持聚合。COUNT(DISTINCT col) 会统计唯一值,两者都会将 NULL 视为一个值,性能通常没有明显差异。

常见问题解答

「DISTINCT 与 GROUP BY 的去重比较」课时是免费的吗?

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

「DISTINCT 与 GROUP BY 的去重比较」这节课中我会学到什么?

了解什么时候应使用 DISTINCT,以及什么时候面试官希望您改用 GROUP BY 你通过在浏览器中直接运行的动手代码来练习 SQL Interview Prep,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

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

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

「DISTINCT 与 GROUP BY 的去重比较」课时需要多长时间?

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

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

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

此课程中的所有课时

  1. 列投影与别名陷阱
  2. 计算列与表达式优先级
  3. DISTINCT 与 GROUP BY 的去重比较
  4. SELECT 中的 CASE 表达式
← 返回 SQL Interview Prep