distinct仅返回唯一值,无法定位重复记录;排查重复需用group by+having统计次数,或mysql 8.0+窗口函数查完整行,也可通过添加唯一索引暴露冲突。

MySQL 中的 DISTINCT 本身不用于“排查”重复记录,而是用于去重查询——它返回的是唯一值结果集,会自动跳过重复行。若想真正定位、识别或分析重复数据,需配合 GROUP BY 和 HAVING,或使用窗口函数(MySQL 8.0+)。直接用 DISTINCT 只能看到“去重后长什么样”,看不到哪些记录重复、重复几次、具体是哪几行。
用 DISTINCT 看去重后的值(只知有重复,不知详情)
适合快速确认某列是否存在重复值,但无法得知重复条数或原始行信息:
-
SELECT DISTINCT column_name FROM table_name;—— 查看该列所有唯一值 - 若结果行数明显少于
SELECT COUNT(*) FROM table_name;,说明该列存在重复 - 注意:
DISTINCT作用于整行(多个字段时),不是单列;SELECT DISTINCT a, b表示 (a,b) 组合唯一
用 GROUP BY + HAVING 找出重复值及出现次数
这是排查重复记录最常用、兼容性最好的方法:
SELECT column_name, COUNT(*) AS cnt FROM table_name GROUP BY column_name HAVING cnt > 1;- 可扩展为多列组合判断重复:
GROUP BY col1, col2 - 加上
ORDER BY cnt DESC能优先看到高频重复项 - 若需查看重复数据的完整行,可搭配子查询或
JOIN关联原表(见下一条)
查出所有重复记录的完整行(不只是重复值)
仅知道“张三”重复了3次还不够,常需定位到这3条原始记录:
- MySQL 8.0+ 推荐用窗口函数:
SELECT * FROM (SELECT *, COUNT(*) OVER (PARTITION BY column_name) AS dup_cnt FROM table_name) t WHERE dup_cnt > 1; - 旧版本可用自连接或子查询:
SELECT t1.* FROM table_name t1 INNER JOIN (SELECT column_name FROM table_name GROUP BY column_name HAVING COUNT(*) > 1) t2 ON t1.column_name = t2.column_name; - 注意:若主键或唯一标识缺失,可能难以区分逻辑重复与真实冗余,建议先检查业务主键设计
辅助手段:添加唯一索引快速暴露重复
在开发或清理阶段,可临时加唯一约束来强制发现冲突:
ALTER TABLE table_name ADD UNIQUE INDEX idx_unique_col (column_name);- 执行失败时 MySQL 会报错并提示首条冲突记录的值(如
Duplicate entry 'xxx' for key 'idx_unique_col') - 适合小表快速验证;大表建议先用
GROUP BY预估重复量,避免锁表时间过长 - 加索引前确保已备份,且明确该字段业务上确实应唯一











