数据库重复行处理:查找并更新submission_file_id重复数据
嘿,我来帮你搞定这个重复数据的处理问题,分两步走,每一步都给你具体的SQL方案和关键注意事项:
第一步:删除同一journal_id下的重复行
我们可以通过窗口函数给每个journal_id+submission_file_id组合的行分配序号,保留序号为1的那条记录,删除其余重复行。以下方案适用于支持窗口函数的数据库(比如MySQL 8.0+、PostgreSQL、SQL Server等):
-- 先运行这个查询,确认要删除的记录范围,避免误删 SELECT * FROM ( SELECT *, ROW_NUMBER() OVER(PARTITION BY journal_id, submission_file_id ORDER BY article_id) AS rn FROM articles_migration ) t WHERE rn > 1; -- 确认无误后,执行删除操作 DELETE FROM articles_migration WHERE (journal_id, submission_file_id, article_id) IN ( SELECT journal_id, submission_file_id, article_id FROM ( SELECT journal_id, submission_file_id, article_id, ROW_NUMBER() OVER(PARTITION BY journal_id, submission_file_id ORDER BY article_id) AS rn FROM articles_migration ) t WHERE rn > 1 );
说明:
PARTITION BY journal_id, submission_file_id会把同一期刊、同一文件ID的行归为一组;ORDER BY article_id用来确定保留哪一行(这里默认保留article_id最小的记录,你可以根据需求改成创建时间、更新时间等其他字段);- 序号
rn>1的就是需要删除的重复行。
如果你的数据库不支持窗口函数(比如MySQL 5.x),可以用关联查询替代:
DELETE a FROM articles_migration a JOIN articles_migration b ON a.journal_id = b.journal_id AND a.submission_file_id = b.submission_file_id AND a.article_id > b.article_id;
这个语句会删除同一journal_id和submission_file_id下article_id更大的行,保留更小的那条。
第二步:更新跨journal_id的重复submission_file_id
第一步处理完成后,剩下的重复submission_file_id都是跨不同journal_id的记录了。我们同样用窗口函数标记需要更新的行,将其中一部分的submission_file_id更新为「原值×10000」:
-- 先查询要更新的记录,确认逻辑正确 SELECT submission_file_id, submission_file_id * 10000 AS new_submission_file_id, rn FROM ( SELECT submission_file_id, ROW_NUMBER() OVER(PARTITION BY submission_file_id ORDER BY journal_id, article_id) AS rn FROM articles_migration ) t WHERE rn > 1; -- 确认无误后,执行更新操作 UPDATE articles_migration SET submission_file_id = submission_file_id * 10000 WHERE (submission_file_id, article_id) IN ( SELECT submission_file_id, article_id FROM ( SELECT submission_file_id, article_id, ROW_NUMBER() OVER(PARTITION BY submission_file_id ORDER BY journal_id, article_id) AS rn FROM articles_migration ) t WHERE rn > 1 );
说明:
PARTITION BY submission_file_id把重复的文件ID分组;ORDER BY journal_id, article_id用来选择哪条保留原值、哪条更新(序号rn>1的行会被更新),你可以调整排序字段来决定具体更新哪一行。
关键注意事项
- 执行删除/更新操作前,一定要先备份数据库,或者开启事务测试:比如MySQL可以用
START TRANSACTION;执行操作后,用SELECT确认结果,没问题就COMMIT;,有问题直接ROLLBACK;,避免数据丢失。
内容的提问来源于stack exchange,提问作者user7190782
相关产品推荐
相关产品推荐

