DISTINCT对多个字段生效的条件是所有指定字段值完全相同才视为重复,即按字段组合整体去重;NULL被视为相同值,DISTINCT必须紧随SELECT后且不可修饰单字段或与聚合函数混用。

DISTINCT 对多个字段生效的条件是什么
DISTINCT 作用于 SELECT 后的所有列,不是对每个字段单独去重,而是对整行组合做唯一性判断。也就是说,只有当所有指定字段的值完全相同时,才算重复行。
常见误解是以为 SELECT DISTINCT col1, col2 会分别去掉 col1 和 col2 的重复值——实际不会,它只保留 (col1, col2) 这个元组不重复的记录。
正确写法与典型错误对比
✅ 正确:直接在 SELECT 后列出多个字段,DISTINCT 自动覆盖全部
SELECT DISTINCT user_id, status, created_date FROM orders;
❌ 错误:试图对部分字段加 DISTINCT(SQL 不支持)
-- 语法错误!DISTINCT 不能只修饰某一个字段 SELECT DISTINCT user_id, status, created_date FROM orders;
⚠️ 注意:DISTINCT 必须紧跟在 SELECT 后,且不能出现在子句中间或和聚合函数混用(除非配合 GROUP BY)。
和 GROUP BY 的区别与取舍
两者都能实现多字段去重,但语义和能力不同:
-
DISTINCT是纯结果去重,不支持额外计算,也不强制要求字段出现在SELECT列表中(但实际必须出现) -
GROUP BY是分组操作,允许搭配MIN()、COUNT()等聚合函数,还能过滤分组(HAVING),但所有非聚合字段都必须出现在GROUP BY子句里 - 性能上,多数引擎对简单
DISTINCT做哈希去重,而GROUP BY可能触发排序或临时表,大数据量时需实测
如果只是要“拿到不重复的 (a,b,c) 组合”,优先用 DISTINCT;如果还要统计每组数量、取最新时间等,就该换 GROUP BY。
NULL 值在多字段 DISTINCT 中怎么算
这是最容易被忽略的细节:SQL 标准中,NULL = NULL 为未知(UNKNOWN),但 DISTINCT 把所有 NULL 视为相同值处理。
例如这两行会被当成重复:
user_id | status | created_date --------+--------+------------- 101 | 'paid' | NULL 101 | 'paid' | NULL
但这一行不会和上面冲突:
101 | 'paid' | '2024-01-01'
所以如果你的业务中 NULL 表示“未设置”而非“相同状态”,要注意这可能导致意外合并。
某些数据库(如 PostgreSQL)支持 DISTINCT ON 来控制按某列去重并取首行,但那是扩展语法,标准 SQL 不通用。

















