DISTINCT用于单列或多列去重,非函数,必须紧跟SELECT后;单列时返回该值首次出现的整行,多列时按组合值去重;NULL视为相同,但NULL与空字符串不同;不可替代GROUP BY的聚合功能。

MySQL 中 DISTINCT 用于单列去重的写法
直接在 SELECT 后加 DISTINCT,作用于紧随其后的字段。它不是函数,不能加括号,也不能只对某一部分字段生效。
-
DISTINCT必须紧跟在SELECT后面,中间不能有换行或注释干扰 - 对单列去重时,结果只保留该列值唯一的行,但返回的是「整行中该列首次出现的那条记录对应的所有字段」——注意:这不是按时间或主键排序后的“第一条”,而是 MySQL 存储引擎扫描顺序下的第一条(不可预测)
- 如果想确保取到某个确定的行(比如最新的一条),
DISTINCT本身做不到,得配合GROUP BY+ 聚合函数或子查询
SELECT DISTINCT user_id FROM orders;
DISTINCT 对多列组合去重的逻辑
当列出多个字段时,DISTINCT 判断的是「字段组合值是否完全相同」,只要其中任意一列不同,就算不同行。
- 例如
SELECT DISTINCT city, province FROM address,会把('Beijing', 'Beijing')和('Beijing', 'Hebei')当作两条不同记录 - 多列
DISTINCT不等于分别对每列去重;它不支持类似DISTINCT city, DISTINCT province这种写法 - 如果某列含
NULL,多个NULL在DISTINCT中被视为相同值(符合 SQL 标准)
SELECT DISTINCT status, category FROM products;
DISTINCT 和 GROUP BY 的关键区别
两者都能实现去重效果,但语义和能力完全不同:DISTINCT 只能返回原始字段,不能做聚合计算;GROUP BY 是分组操作,天然支持 COUNT()、MAX() 等聚合函数。
- 用
DISTINCT无法回答“每个城市有多少用户”,必须改用GROUP BY city -
GROUP BY要求SELECT中所有非聚合字段都出现在GROUP BY子句里(严格模式下),而DISTINCT没这个限制 - 性能上,简单去重场景
DISTINCT通常更快;但需要关联统计时,GROUP BY是唯一选择
容易被忽略的 NULL 和空字符串陷阱
DISTINCT 会把所有 NULL 视为同一值,但不会把空字符串 '' 和 NULL 当作相同——这是初学者常混淆的点。
- 表中若有
name字段:包含NULL、''、'Alice'、'Alice',SELECT DISTINCT name返回 3 行(NULL算 1 行,''算 1 行,'Alice'算 1 行) - 如果业务上认为
NULL和''都代表“未填写”,需先用COALESCE(name, '')或IFNULL(name, '')统一处理再DISTINCT - 字符集和排序规则(collation)也会影响去重结果,比如大小写敏感的 collation 下,
'ABC'和'abc'会被视为不同值










