distinct是select修饰关键字而非函数,正确写法为select distinct name from users;它按行去重,null视为相同值,不保证顺序,不可混用聚合函数,多列去重需完全匹配,性能受字段数量和长度影响。

MySQL中DISTINCT对单列去重的写法和常见误区
DISTINCT不是函数,是SELECT的修饰关键字,写在字段列表最前面。很多人误写成SELECT DISTINCT(name),这实际会报语法错误——括号会让MySQL尝试解析为函数调用。
正确写法是:SELECT DISTINCT name FROM users;
- 如果
name列有NULL值,DISTINCT会把所有NULL视为同一值,只保留一行 -
DISTINCT作用于整行结果,但单列时效果等价于该列去重;它不改变原始数据,只影响查询输出 - 不能在
DISTINCT后混用普通字段和聚合函数(如SELECT DISTINCT name, COUNT(*)),会报错
多列组合去重必须理解“行级唯一”的含义
写SELECT DISTINCT name, city FROM users;,去重逻辑是:只有name和city两列值**完全相同**的行才被合并。哪怕只有一列不同,就算作不同记录。
例如:('Alice', 'Beijing') 和 ('Alice', 'Shanghai') 不会被去重;('Bob', 'Beijing') 和 (NULL, 'Beijing') 也不会合并——因为NULL = NULL在SQL中为UNKNOWN,不成立。
- 多列
DISTINCT无法指定“以某列为基准,保留其他列任意一条”,它只做严格匹配 - 若想按
name去重但取最新一条的city,得用GROUP BY配合MAX(created_at)或窗口函数,而不是DISTINCT - 性能上,多列
DISTINCT需要临时排序或哈希,字段越多、值越长,内存消耗越大
DISTINCT和GROUP BY在去重场景下的关键区别
表面看SELECT DISTINCT a,b FROM t; 和 SELECT a,b FROM t GROUP BY a,b; 结果一样,但底层行为完全不同。
-
DISTINCT是查询优化器决定如何实现(可能走临时表、排序或松散索引扫描),不保证顺序,也不支持聚合计算 -
GROUP BY强制分组,允许接MIN()、MAX()、COUNT()等聚合函数,还能配合HAVING过滤分组 - 当表有合适索引(如
(a,b)联合索引)时,GROUP BY a,b可能避免临时表,而DISTINCT a,b不一定能利用同一索引优化 - MySQL 8.0+ 对
DISTINCT做了更多优化,但在复杂WHERE条件下,GROUP BY的执行计划往往更可控
容易被忽略的NULL处理和ORDER BY依赖
DISTINCT本身不保证返回顺序。如果你写了SELECT DISTINCT city FROM locations ORDER BY city;,排序生效是因为ORDER BY独立起作用;但若漏掉ORDER BY,结果顺序由存储引擎和执行路径决定,不可靠。
-
NULL在排序中默认排在最前(ASC)或最后(DESC),但DISTINCT合并时仍视所有NULL为等价——这点和GROUP BY一致 - 如果业务要求“去重后取每组第一条”,不要依赖
DISTINCT隐式顺序,应明确用ROW_NUMBER() OVER (PARTITION BY ... ORDER BY ...)(MySQL 8.0+)或子查询模拟 - 在大表上用
DISTINCT且无索引支撑时,容易触发Using temporary; Using filesort,查慢日志里能看到明显提示











