distinct必须紧随select后且不加括号,作用于整行去重;错误写法如select distinct(name)会报语法错误;它基于所有select字段组合全匹配去重,null视为相同值;order by字段须在select列表中;distinct与group by语义及执行逻辑不同,不可随意互换。

SELECT DISTINCT必须紧挨SELECT,不能加括号
DISTINCT不是函数,也不是字段修饰符,它是作用于整行结果的查询修饰符。写成SELECT DISTINCT(name)或SELECT DISTINCT (id, name)会直接报错——PostgreSQL提示syntax error at or near "(",MySQL报ERROR 1064。正确写法只有一种:SELECT DISTINCT id, name,中间不能有空格、换行或括号干扰。
DISTINCT去重基于整行值完全匹配,NULL视为相同
它不按单列“分别去重”,而是看所有SELECT字段组成的元组是否完全一致。比如SELECT DISTINCT country, city FROM users,只有country和city两个值都相同时才合并;若country相同但city不同,两行都保留。多个NULL也被当成相同值处理,所以SELECT DISTINCT status FROM t中所有NULL只返回一行。
ORDER BY字段必须出现在SELECT列表中
用了DISTINCT后,ORDER BY只能引用SELECT里明确写出的字段或别名。例如SELECT DISTINCT name FROM users ORDER BY created_at在MySQL 8.0+(启用ONLY_FULL_GROUP_BY)下必然报错ERROR 1055。解决方式只有两个:
• 把排序字段也放进SELECT(但会改变去重粒度)
• 改用子查询:SELECT name FROM (SELECT DISTINCT name FROM users) t ORDER BY name
DISTINCT和GROUP BY语义不同,别随便互换
SELECT DISTINCT a, b FROM t和SELECT a, b FROM t GROUP BY a, b结果可能一样,但执行逻辑完全不同:
• DISTINCT是纯结果集去重,不支持聚合、不能接HAVING,也不保证顺序
• GROUP BY是分组基础,后续可跟COUNT()、MIN()等,且能利用索引加速
大数据量时,ClickHouse或某些MySQL版本下GROUP BY反而比DISTINCT更省内存——因为后者常触发全量哈希,容易OOM
真正麻烦的地方不在语法,而在去重时机:DISTINCT发生在WHERE、JOIN全部执行完之后,中间膨胀无法避免。想优化,得从JOIN条件或子查询入手,而不是指望DISTINCT“聪明地提前裁剪”。










