在数据库日常维护中,重复数据是常见的脏数据问题,使用JOIN操作可以高效地完成重复记录的定位与删除,比传统的子查询方式性能更优,逻辑也更清晰。

一、先通过JOIN找出重复记录
要找出表中的重复记录,首先需要明确重复的判断维度,比如同一用户的多条相同手机号记录,或者同一订单的多条相同订单号记录。我们可以通过自连接的方式,匹配重复字段来定位重复数据。
假设有一张用户表user_info,结构如下:
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | INT | 主键自增 |
| user_name | VARCHAR(50) | 用户名 |
| phone | VARCHAR(20) | 手机号 |
| create_time | DATETIME | 创建时间 |
现在需要找出手机号重复的所有用户记录,使用INNER JOIN自连接的查询语句如下:
-- 查询手机号重复的所有记录,保留重复组中id最小的作为基准 SELECT a.* FROM user_info a INNER JOIN user_info b ON a.phone = b.phone -- 匹配重复的手机号 AND a.id > b.id; -- 排除id最小的基准记录,剩下的都是重复记录
上述查询会返回所有重复的非基准记录,其中a.id > b.id的作用是保证每组重复数据中只保留id最小的那一条,其余的都会被筛选出来。
二、使用DELETE JOIN删除重复记录
定位到重复记录后,就可以使用DELETE JOIN语法直接删除重复数据,不需要先导出再导入,操作更便捷。不同数据库的DELETE JOIN语法略有差异,下面分别给出MySQL和SQL Server的示例。
1. MySQL中的DELETE JOIN用法
MySQL支持直接在DELETE语句中使用JOIN,删除重复记录的同时保留每组中id最小的那条:
-- 删除user_info表中手机号重复的记录,保留每组id最小的记录 DELETE a FROM user_info a INNER JOIN user_info b ON a.phone = b.phone AND a.id > b.id;
这里的DELETE a表示删除连接后的a表记录,也就是所有重复的非基准记录,执行后每组手机号只会保留id最小的那一条数据。
2. SQL Server中的DELETE JOIN用法
SQL Server的DELETE语法不支持直接在DELETE后加表别名,需要通过子查询或者CTE的方式实现,示例如下:
-- 使用CTE定位重复记录,再执行删除
WITH duplicate_records AS (
SELECT a.id
FROM user_info a
INNER JOIN user_info b
ON a.phone = b.phone
AND a.id > b.id
)
DELETE FROM user_info
WHERE id IN (SELECT id FROM duplicate_records);
这种方式先通过CTE找出所有需要删除的重复记录id,再批量删除,逻辑和MySQL的实现效果一致。
三、使用注意事项
- 执行DELETE JOIN前一定要先执行对应的SELECT JOIN查询,确认筛选出来的都是需要删除的重复记录,避免误删有效数据。
- 如果表数据量较大,建议先给连接字段(比如示例中的phone字段)添加索引,能大幅提升JOIN查询和删除的效率。
- 如果需要保留的是最新创建的记录,可以把连接条件中的
a.id > b.id改成a.create_time < b.create_time,根据实际需求调整保留规则。 - 操作前最好对表做全量备份,防止操作失误导致数据无法恢复。
注意:DELETE JOIN操作属于高危数据修改操作,生产环境执行前必须经过测试环境的验证,确认逻辑无误后再操作。
SQL_JOIN数据去重DELETE_JOIN重复记录查询修改时间:2026-07-04 06:03:21