DISTINCT是对SELECT后所有字段组合去重,而非单字段去重;正确写法为SELECT DISTINCT col1, col2 FROM t,表示对(col1,col2)组合唯一性判断,若只需求col1唯一值,须单独写SELECT DISTINCT col1 FROM t。

DISTINCT 不是按单字段去重,而是对整行去重
直接写 SELECT DISTINCT column_a, column_b FROM t 并不能“只对 column_a 去重”,它会对 (column_a, column_b) 这个组合去重。如果你只想看 column_a 的唯一值,必须只选它:SELECT DISTINCT column_a FROM t。一旦带上其他字段,就不再是“按某字段去重”,而是“按字段组合去重”。这是绝大多数人踩坑的第一步。
想保留其他字段时,DISTINCT 失效了怎么办
常见需求是:“每个部门只取一个人的信息(比如 id 最小的那个)”,这时 DISTINCT 完全无能为力——它不能指定保留哪一行,也不能配合 ORDER BY 或聚合函数筛选行。
- 错误写法:
SELECT DISTINCT dept, name, id FROM employees ORDER BY id——ORDER BY在DISTINCT后无效,且结果不可控 - 正确思路:用窗口函数先给每组编号,再过滤
- MySQL 8.0+ / PostgreSQL / SQL Server 可用:
SELECT dept, name, id FROM ( SELECT *, ROW_NUMBER() OVER (PARTITION BY dept ORDER BY id) AS rn FROM employees ) t WHERE rn = 1;
- 老版本 MySQL(
GROUP BY 能替代 DISTINCT 吗?什么时候该用
GROUP BY 和 DISTINCT 表面结果可能一样,但能力完全不同。如果只是要“列出所有不重复的部门名”,两者都行;但只要涉及“保留某条具体记录”或“需要聚合计算”,就必须用 GROUP BY。
- 仅去重:
SELECT dept FROM employees GROUP BY dept等价于SELECT DISTINCT dept FROM employees - 带统计:
SELECT dept, COUNT(*) FROM employees GROUP BY dept——DISTINCT做不到 - 想取每组最新一条:
SELECT dept, MAX(id) FROM employees GROUP BY dept,但注意:这只能拿到dept和MAX(id),拿不到对应那条记录的name等字段 - 真正要完整行数据,还是得回到窗口函数
含 NULL 值时去重行为容易被忽略
大多数数据库把所有 NULL 视为相等,所以 SELECT DISTINCT column_a FROM t 中,哪怕有 10 行 column_a IS NULL,结果也只返回一个 NULL。这和 WHERE column_a = column_a 的逻辑不一致(后者 NULL = NULL 为 UNKNOWN),容易在调试时误判。
真正难的不是语法,而是厘清你要的是“唯一值列表”,还是“去重后保留原始行中某条代表记录”。前者用 DISTINCT 或 GROUP BY 就够;后者必须引入排序逻辑和行号控制,绕不开窗口函数或子查询。

















