在mysql数据库的日常运维和开发工作中,数据表中出现重复记录是比较常见的问题,重复数据可能会导致统计结果不准确、业务逻辑异常等情况,因此需要掌握快速查找重复记录的方法。

单字段重复记录查找
当只需要判断某一个字段存在重复值时,可以使用GROUP BY结合HAVING子句来实现,这是最基础的重复记录查找方式。
假设我们有一张用户表user,结构如下:
CREATE TABLE user (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL,
phone VARCHAR(20)
);
如果要查找username字段重复的所有记录,可以先统计每个username出现的次数,再筛选出出现次数大于1的分组,最后关联原表获取完整记录:
-- 查找username重复的所有记录
SELECT u.*
FROM user u
JOIN (
SELECT username
FROM user
GROUP BY username
HAVING COUNT(username) > 1
) t ON u.username = t.username
ORDER BY u.username;
多字段重复记录查找
实际业务中更多需要判断多个字段组合重复的情况,比如同时判断username和email都相同的记录才算重复,此时只需要在GROUP BY后添加多个字段即可。
查找username和email同时重复的记录示例:
-- 查找username和email同时重复的所有记录
SELECT u.*
FROM user u
JOIN (
SELECT username, email
FROM user
GROUP BY username, email
HAVING COUNT(*) > 1
) t ON u.username = t.username AND u.email = t.email
ORDER BY u.username, u.email;
查找重复记录并保留一条
有时候我们需要查找重复记录,同时只保留其中一条(比如保留id最小的记录),其余的重复记录标记为需要删除的目标,可以通过子查询实现。
示例:查找username重复的记录,保留id最小的那条,其余作为重复记录输出:
-- 查找重复记录,保留id最小的一条,输出其余重复记录
SELECT u.*
FROM user u
WHERE u.id NOT IN (
SELECT MIN(id)
FROM user
GROUP BY username
HAVING COUNT(username) > 1
) AND u.username IN (
SELECT username
FROM user
GROUP BY username
HAVING COUNT(username) > 1
)
ORDER BY u.username;
注意事项
- 使用
COUNT(*)和COUNT(字段名)的区别在于,COUNT(*)会统计所有行,COUNT(字段名)会忽略该字段为NULL的行,需要根据实际场景选择。 - 如果数据表数据量非常大,建议先给分组用到的字段添加索引,可以提升查询效率。
- 执行删除重复记录的操作前,一定要先备份数据,避免误删重要数据。