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())或其他标记方式转换,但要注意这会影响索引使用和可读性。
