select distinct未去重最常见的原因是字段组合本身不重复,因其对整行生效而非单列;null被视为相同值会被合并,末尾空格可能影响比较结果。

SELECT DISTINCT 为什么没去重?
最常见的原因是字段组合本身不重复——DISTINCT 对整行生效,不是对某一个列。比如 SELECT DISTINCT name, age FROM users,只要 (name, age) 这一对值不完全相同,就算有重复 name 也会保留多行。
- 想只按
name去重?得用GROUP BY name配合聚合函数,或者子查询 +ROW_NUMBER() -
NULL被视为相同值,多个NULL在同一字段里会被合并成一行 - 字符串末尾空格在某些数据库(如 MySQL 的
TEXT类型)可能影响比较结果,导致本该去重的没去掉
DISTINCT 和 GROUP BY 选哪个?
如果只是取唯一值,DISTINCT 更直接;但一旦需要附加计算(比如每个分组的最新时间、统计数量),就必须上 GROUP BY。两者语义不同:DISTINCT 是结果去重操作,GROUP BY 是分组聚合操作。
-
DISTINCT不能配合WHERE以外的聚合逻辑,例如“每个category下价格最高的商品”无法单靠它实现 - 部分数据库(如 PostgreSQL)允许
DISTINCT ON (col),可指定按某列优先去重,但这是扩展语法,MySQL 和 SQL Server 不支持 - 性能上,
DISTINCT通常隐式触发排序或哈希去重,大数据量时可能比带索引的GROUP BY更慢
ORDER BY 和 DISTINCT 能一起用吗?
能,但有限制:ORDER BY 的字段必须出现在 SELECT 列表中(除非是常量或聚合表达式)。否则会报错,比如 SELECT DISTINCT name FROM users ORDER BY created_at 在大多数数据库里非法。
- 想按某个未选字段排序?得改写为子查询,例如先
DISTINCT name,再JOIN原表取最大created_at - MySQL 5.7+ 默认开启
ONLY_FULL_GROUP_BY,会让很多看似能跑的DISTINCT + ORDER BY实际报错,别以为是语法问题,先查 SQL mode -
ORDER BY不影响去重逻辑,只决定最终结果顺序
替代 DISTINCT 的轻量方案有哪些?
当数据量大、去重字段多、且业务允许“近似唯一”时,可以考虑更省资源的方式。
- 用
EXISTS或IN替代多表DISTINCT:比如查“有订单的用户”,SELECT id FROM users WHERE EXISTS (SELECT 1 FROM orders WHERE orders.user_id = users.id)比SELECT DISTINCT users.id FROM users JOIN orders ON ...更快 - 临时表 + 主键约束:插入前加
INSERT IGNORE(MySQL)或ON CONFLICT DO NOTHING(PostgreSQL),靠唯一索引拦重 - 应用层去重更灵活,但要注意网络传输和内存开销——特别是返回几千行再过滤,不如让数据库干
DISTINCT 时,最容易被忽略的是它的“全字段语义”和对 NULL 的处理方式;很多人调了半天发现没去重,最后发现是多选了一个时间戳字段。










