mysql 中 distinct 是 select 查询语句里面的关键字,作用是对查询返回的结果集进行去重,剔除重复的数据行,只保留唯一记录,它写在 select 之后字段列表之前,核心逻辑是把后面所有字段组合起来当做整体判断重复,不是单独对某一列去重,这个是新手最容易踩坑的关键点,distinct 经常配合 count 函数统计不重复记录数量,适合分类统计获取唯一值场景,比如查询用户表里面不重复的城市,订单表里面不重复的商品类别,掌握 mysql 中 distinct 用法,还要理解它执行原理性能限制,以及和 group by 去重的区别,这样写 SQL 的时候可以根据业务场景选择更合适的方案。
基础语法格式
select distinct 字段名 from 表名 where 查询条件
如果是多个字段,写法就是 select distinct 字段 1 字段 2 from 表名
这里重点记住,distinct 是对后面全部字段的组合做去重,只有所有列的值全部一样,才会判定为重复行,如果字段 1 相同但是字段 2 不一样,这条记录依旧会保留。
分场景使用示例
| 使用场景 | SQL 写法 | 说明 |
|---|---|---|
| 单列去重 | select distinct city from user | 只对 city 这一列去重,返回所有不重复城市 |
| 多列组合去重 | select distinct city age from user | city 和 age 同时相同才判定重复,任意一列不同就保留 |
| 搭配 where 条件 | select distinct city from user where status=1 | 先筛选符合条件的数据,再执行 distinct 去重 |
| 统计去重总数 | select count(distinct city) from user | 统计不重复 city 一共有多少个,这是高频用法 |
底层执行原理
mysql 执行查询的时候,会先执行 from 表读取数据,再执行 where 过滤,之后执行 distinct 对结果集做排序或者哈希运算识别重复行,最后输出唯一行。如果表数据量很大,distinct 会消耗较多内存和 CPU 资源,因为需要比对全部字段组合,大表场景下性能会明显下降,这也是大数据量查询经常改用 group by 的原因。
distinct 和 group by 对比
| 对比项 | distinct | group by |
|---|---|---|
| 核心目的 | 单纯去除重复行 | 分组聚合,搭配 sum count max 等聚合函数 |
| 多列逻辑 | 多列组合去重 | 按照分组字段分组,每组返回一行 |
| 性能 | 大表性能一般 | 合理索引加持下性能更优 |
| 扩展能力 | 只能去重,不能做复杂聚合 | 支持丰富聚合计算,业务灵活性更强 |
常见错误写法
错误写法一 distinct 只写在部分字段前面,比如 select id distinct city from user,这个语法不合法,mysql 中 distinct 只能放在 select 后面所有查询字段的最前面,不能单独给某一列加 distinct,其他字段保留重复。
错误写法二 误以为多列 distinct 只针对第一个字段去重,很多新手写 select distinct city age,以为只对 city 去重,age 随便显示,实际是 city 加 age 组合判断,会出现同一个 city 对应多条不同 age 记录。
错误写法三 超大表直接使用 distinct,没有加索引,造成查询卡顿,这种情况建议给参与去重的字段建立联合索引,优化执行效率。
进阶使用要点
distinct 不能和 all 关键字同时使用,all 是默认全部保留,distinct 是开启去重,二者互斥。
如果字段里面存在 null 值,distinct 会把所有 null 当成同一条重复记录,结果集只会保留一行 null。
当需要同时去重并且排序,可以搭配 order by,注意 order by 的字段最好在 distinct 字段列表里面,否则部分版本会出现报错。
综合来看 mysql 中 distinct 用法核心就是结果集整行组合去重,单列去重最简单,多列是组合判断,统计数量使用 count distinct,大表业务优先评估性能,需要聚合计算的时候优先考虑 group by 替代 distinct。
【常见问题】
问题 1 mysql 中 distinct 可以只对其中一列去重吗
回答 1 mysql 中 distinct 不能单独只对其中一列去重,mysql 中 distinct 是对后面所有查询字段整体组合判断重复,如果需要单列去重同时保留其他字段,需要改用其他 SQL 方案。
问题 2 mysql 中 distinct 和 group by 去重哪个性能更好
回答 1 同等条件下大表场景 mysql 中 group by 搭配联合索引性能通常优于 mysql 中 distinct,distinct 没有聚合能力,单纯去重可以使用,复杂统计推荐 group by。
问题 3 mysql 中 distinct 遇到 null 值会怎么处理
回答 3 mysql 中 distinct 会把多条 null 识别成重复记录,最终结果集只保留一条 null,这是 mysql 中 distinct 固定处理规则。
问题 4 mysql 中 distinct 可以写在 where 后面吗
回答 4 mysql 中 distinct 不能写在 where 后面,mysql 中 distinct 位置固定,必须放在 select 关键字之后查询字段列表的最前方。
【免责申明】
本教程基于 MySQL 通用语法编写,不同 MySQL 版本执行优化细节存在差异,SQL 执行性能受表数据量索引影响,内容仅供学习参考,生产环境 SQL 优化请结合 explain 执行计划评估。


