首页/数据/SQL 速查/DISTINCT 去重

DISTINCT 去重

对结果集去重:作用于整个 SELECT 列清单,不是单列;统计去重计数用 COUNT(DISTINCT col),注意 NULL 不参与计数。

SQL 速查数据更新于 2026-10-13

DISTINCT 是什么

DISTINCT 对结果集去重,作用于整个 SELECT 列清单,而不是某一列。常见误解是 SELECT DISTINCT a, b 只按 a 去重,实际是按 (a, b) 的组合去重。统计去重个数要用 COUNT(DISTINCT col),它与 COUNT(col) 的结果不同。DISTINCT 通常需要排序或哈希来实现,数据量越大代价越高,能靠索引顺序天然去重的场景应尽量避免额外的 DISTINCT。

基本信息

作用对结果集按整行去重
作用范围整个 SELECT 列清单,不是单列
去重计数COUNT(DISTINCT col),与 COUNT(col) 不同
实现方式通常需要排序或哈希,代价随结果集增长
与 GROUP BY只做去重时两者等价,需要聚合时必须用 GROUP BY
适用平台标准 SQL,MySQL 8.0 与 PostgreSQL 一致

典型使用场景

  • 取唯一值列表:城市、类目、标签等枚举值
  • 生成下拉选项:后台筛选框的可选值
  • 去重计数:COUNT(DISTINCT user_id) 求独立用户数
  • 数据体检:去掉重复视角看真实基数,评估索引选择性
  • 多列组合去重:检查 (a, b) 组合是否唯一
  • 中间结果去重:UNION 两个查询结果时有自动去重效果

示例

示例
SELECT DISTINCT city FROM users;               # 单列去重
SELECT DISTINCT city, province FROM users;     # 按组合去重,不是只按 city

SELECT COUNT(DISTINCT user_id) FROM orders;    # 去重计数

-- 只去重不聚合时,与 GROUP BY 等价
SELECT city FROM users GROUP BY city;

-- 需要同时去重并聚合时用 GROUP BY
SELECT city, COUNT(*) FROM users GROUP BY city;

相关写法对照

写法含义注意
SELECT DISTINCT city按 city 去重单列时最直观
SELECT DISTINCT a, b按 (a,b) 组合去重不是只按 a 去重
COUNT(DISTINCT col)去重计数忽略 NULL
GROUP BY a分组去重可同时做聚合
UNION合并并去重UNION ALL 不去重更快
DISTINCT 加在 SELECT 后面,作用于所有输出列;只要多输出一列,去重粒度就随之变化,改 SQL 时容易在这里踩坑。
DISTINCT 与 ORDER BY 一起用时会先排序再去重,结果顺序可能变化;需要固定顺序就显式写 ORDER BY。
如果查询原本要按某列去重并取该组的其他字段,DISTINCT 表达不了,改用 GROUP BY 或 ROW_NUMBER 选行。
DISTINCT 与 GROUP BY 在只做去重时等价,选哪个看上下文:要顺带看每组的数量就用 GROUP BY,纯取唯一值用 DISTINCT 更直观。

易错点

  • 以为 DISTINCT 只作用于某一列,SELECT DISTINCT a, b 实际按组合去重,结果行数与预期不符
  • 多输出一列导致去重粒度变化,接口返回的行数突然变多
  • 在列上加 DISTINCT 却仍按另一列排序,误以为结果已按该列唯一
  • 大结果集上用 DISTINCT 去重,排序与临时表开销明显,本可通过索引避免
  • 把 DISTINCT 当成性能优化手段,实际常是掩盖了连接放大或数据重复的根本问题

数据来源与参考

  • MySQL 8.0 Reference Manual · DISTINCT
  • PostgreSQL Documentation · DISTINCT
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌