如何删除允许重复ID的表中重复记录,仅保留每个ID唯一条目?
删除Student表重复ID记录的单条SQL方案
嗨,这个需求在日常数据库操作里挺常见的,我给你整理了几种主流数据库下的单条SQL解决方案,你可以根据自己使用的数据库来选择:
MySQL 版本
方法1:利用自连接(适配所有MySQL版本)
如果你的表有主键或唯一标识列(比如自增的专属ID、创建时间create_time这类能区分记录的字段),可以用自连接的方式精准删除重复项:
DELETE s1 FROM student s1 JOIN student s2 ON s1.id = s2.id AND s1.student_unique_id > s2.student_unique_id;
这里的s1.student_unique_id > s2.student_unique_id是指定保留student_unique_id更小的那条记录,你可以根据需求改成<保留更大的,或者换成create_time来保留最早/最新的记录。
方法2:窗口函数(MySQL 8.0及以上版本)
如果你的MySQL版本支持窗口函数,这个方法更直观,甚至不需要额外的唯一列(有唯一列的话排序会更可控):
DELETE FROM student WHERE id IN ( SELECT id FROM ( SELECT id, ROW_NUMBER() OVER (PARTITION BY id ORDER BY (SELECT NULL)) AS rn FROM student ) t WHERE rn > 1 );
解释一下:PARTITION BY id会把相同ID的记录分成一组,ROW_NUMBER()给每组的记录编序号,rn > 1就是重复的冗余记录,我们把这些删掉。如果想保留特定的记录(比如最新创建的),把ORDER BY (SELECT NULL)换成ORDER BY create_time DESC即可。
SQL Server 版本
SQL Server用CTE结合窗口函数的方式非常简洁:
WITH DuplicateStudents AS ( SELECT *, ROW_NUMBER() OVER (PARTITION BY id ORDER BY (SELECT NULL)) AS rn FROM student ) DELETE FROM DuplicateStudents WHERE rn > 1;
同样,把ORDER BY换成业务上有意义的字段,就能指定保留哪一条记录。
Oracle 版本
Oracle可以利用内置的ROWID(每条记录的唯一标识符)来实现:
DELETE FROM student WHERE ROWID NOT IN ( SELECT MIN(ROWID) FROM student GROUP BY id );
这个语句会保留每个ID组里ROWID最小的那条记录,如果你想保留最大的,把MIN换成MAX就行。
重要注意事项
- 执行前务必备份数据!或者先把
DELETE改成SELECT *,确认要删除的记录是不是你预期的,避免误删。 - 如果表中没有任何唯一标识列,
ORDER BY (SELECT NULL)会随机保留一条记录,这种情况下最好加上业务上有意义的排序条件,确保保留的是你需要的那条。
内容的提问来源于stack exchange,提问作者srik123
相关产品推荐
相关产品推荐

