distinct是sql关键字而非函数,必须紧随select后、字段前,不可加括号;加括号如distinct(col)在多数数据库报错,mysql虽兼容但属陷阱,正确写法为select distinct col1, col2 from table。

DISTINCT 不是函数,是关键字,用错位置会直接报错
为什么 DISTINCT 不能加括号写成 DISTINCT(...)
很多人看到“DISTINCT 函数”就下意识写成 SELECT DISTINCT(name) FROM users;,这在绝大多数数据库(如 PostgreSQL、SQL Server、SQLite)中会报错:ERROR: syntax error at or near "("。MySQL 虽然允许这种写法,但实际行为是忽略括号、当作普通 DISTINCT name 处理,属于历史兼容陷阱。
-
DISTINCT是 SQL 的查询修饰符(set quantifier),作用于整个SELECT列表,不是函数,不接受参数 - 正确写法只有
SELECT DISTINCT col1, col2 FROM table;,括号只用于函数调用或分组表达式 - 想对单列去重?直接写
SELECT DISTINCT name FROM users;即可
多列 DISTINCT 是按行去重,不是对每列单独去重
执行 SELECT DISTINCT country, city FROM addresses; 时,数据库检查的是「country + city」这一整行是否重复,而不是分别把 country 和 city 各自去重。比如数据有:('CN', 'Beijing')、('CN', 'Shanghai')、('US', 'Beijing'),结果会返回全部三行——因为没有任意两行在两个字段上完全相同。
- 如果只想获取不重复的国家列表,就只选一列:
SELECT DISTINCT country FROM addresses; - 如果想先按国家分组、再取每个国家一个城市,得用
GROUP BY或窗口函数,不能靠DISTINCT -
DISTINCT在大数据量下性能开销大,因为它需要内部排序或哈希去重,比带索引的GROUP BY更重
DISTINCT 和 GROUP BY 什么情况下能互换?
当查询只包含纯列名(无聚合函数、无表达式)、且所有列都出现在 GROUP BY 子句中时,SELECT DISTINCT a, b FROM t 和 SELECT a, b FROM t GROUP BY a, b 语义等价。但二者底层机制不同:
-
DISTINCT是去重操作,不保证返回顺序(除非显式加ORDER BY) -
GROUP BY是分组操作,部分数据库(如 MySQL 5.7+ 默认 SQL 模式)要求SELECT中所有非聚合字段必须出现在GROUP BY中,否则报错:Expression #1 of SELECT list is not in GROUP BY clause - 一旦加了
COUNT(*)或MAX(created_at),就只能用GROUP BY,DISTINCT无法替代
容易被忽略的 NULL 处理细节
多个 NULL 值在 DISTINCT 下被视为相同值。例如 SELECT DISTINCT status FROM orders; 中,所有 status IS NULL 的记录只会保留一行 NULL 结果。这点和 GROUP BY 一致,但和某些应用层去重逻辑(比如 JavaScript 的 Set)不同——后者可能把 null 和 undefined 当作不同值。
- 如果业务上需要区分 “明确为空” 和 “未填写”,建议用字符串标记(如
'NULL_VALUE')代替 SQLNULL,避免去重误合并 -
DISTINCT对大小写敏感性取决于字段的 collation(如utf8mb4_0900_as_cs区分,utf8mb4_0900_ai_ci不区分),不是数据库全局设置 - 嵌套查询里用
DISTINCT要小心:外层SELECT DISTINCT *无法消除内层已去重但结构不同的行
真正难的不是写对 DISTINCT,而是判断该不该用它——很多需求表面要“去重”,实际要的是“取最新一条”“取最高分”“去重后计数”,这时候 DISTINCT 只是半截解法。











