DISTINCT作用于整行而非单列,返回唯一组合;ORDER BY字段必须在SELECT列表中;DISTINCT与GROUP BY语义性能不同;NULL在DISTINCT中被视为相同值。

DISTINCT 只能作用于 SELECT 后的所有列
DISTINCT 不是独立修饰某一个字段的关键词,它对整个 SELECT 行生效。写成 SELECT DISTINCT name, age FROM user 表示“返回所有唯一的 (name, age) 组合”,而不是“只对 name 去重”。如果想按某个字段去重并取最新/某条记录,DISTINCT 无法直接做到,得用 GROUP BY 或窗口函数。
ORDER BY 必须出现在 DISTINCT 之后且只能引用 SELECT 中的列
MySQL 要求 ORDER BY 的字段必须出现在 SELECT DISTINCT 的字段列表中,否则会报错 ERROR 1055(在 sql_mode=ONLY_FULL_GROUP_BY 下尤其严格)。比如下面语句非法:
SELECT DISTINCT name FROM user ORDER BY created_at;
因为 created_at 没出现在 SELECT 列表里。合法写法是:
SELECT DISTINCT name, created_at FROM user ORDER BY created_at;
或者改用子查询或 GROUP BY 实现排序逻辑。
DISTINCT 和 GROUP BY 在语义和性能上不等价
虽然 SELECT DISTINCT a, b FROM t 和 SELECT a, b FROM t GROUP BY a, b 结果通常一致,但二者底层处理不同:
-
DISTINCT是去重操作,MySQL 可能用临时表 + 排序或哈希去重 -
GROUP BY是分组聚合操作,即使没用聚合函数,也会触发分组逻辑,可能更慢、内存占用更高 - 某些版本 MySQL 对
DISTINCT有专门优化(如松散索引扫描),而GROUP BY可能强制使用临时表
如果只是单纯去重,优先用 DISTINCT;如果后续要加 COUNT()、MAX() 等,自然用 GROUP BY。
NULL 值在 DISTINCT 中被视为相同值
MySQL 把所有 NULL 当作相等来处理。例如表中有三行:(1, NULL)、(2, NULL)、(3, NULL),执行:
SELECT DISTINCT col2 FROM t;
结果只返回一个 NULL,不是三个。这点和 UNIQUE 约束行为一致,但容易在统计去重数量时误判——比如 COUNT(DISTINCT col2) 会把全部 NULL 算作 1 次。
如果业务上需要区分“多个 NULL 是否算多次”,就得提前用 IFNULL(col2, UUID()) 或其他标记方式转换,但要注意这会影响索引使用和可读性。










