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'会被视为不同值
