MySQL删除重复数据保留最小id一条SQL MySQL
前言
表中同一业务字段出现多条重复记录,需要只保留一条、删除其余,常见于手机号、订单号、用户名重复。直接 DELETE 容易误删保留项,需要先定位重复组、再按最小 id 保留。本文讲解用 GROUP BY 找重复、自连接删除、窗口函数保留最小 id 的多种写法。
操作步骤
1. 先查重复记录确认范围
SELECT phone, COUNT(*) c
FROM users
GROUP BY phone
HAVING c > 1;
2. 自连接删除多余重复
DELETE u1 FROM users u1
JOIN users u2
WHERE u1.id > u2.id AND u1.phone = u2.phone;
同一 phone 保留 id 最小的一条。
3. 窗口函数方式(MySQL8)
DELETE FROM users
WHERE id IN (
SELECT id FROM (
SELECT id, ROW_NUMBER() OVER (PARTITION BY phone ORDER BY id) rn
FROM users
) t WHERE rn > 1
);
4. 删除前先备份相关数据
CREATE TABLE users_backup AS SELECT * FROM users;
5. 验证重复已清除
SELECT phone, COUNT(*) FROM users GROUP BY phone HAVING COUNT(*)>1;
无返回即去重完成。
常见坑
- 没备份直接删,删错无法恢复。
- 自连接条件写错,把保留项也删掉。
- 唯一业务键没加唯一索引,删完还会再产生重复。
- 大表删除产生大量锁和日志,分批删更稳。
- 多字段联合重复(phone+email),PARTITION BY 要写全。
- MySQL8 之前没有窗口函数,用自连接方案。
- 外键约束下删除失败,需先处理关联表。
总结
去重核心:按业务键 GROUP BY 找重复,保留最小 id,删除其余。删前备份、删后验证,并给业务键加唯一索引防止复发。大表分批删除减少锁表,多字段重复要把所有键放进分组条件。
遇到问题加QQ23979811 协助处理