MySQL中合并重复行关联引用并清理重复分类数据的实现方案问询
解决MySQL分类表重复数据并同步更新关联标签表的方案
嘿,我完全懂你现在的处境——作为MySQL新手,碰到这种要兼顾数据关联的清理工作确实头大,手动改既费时间又容易出错。针对你的MySQL 5.7.21版本,我整理了一套可以定期执行的SQL脚本,分三步完成,既能保证数据关联不失效,又能清理掉重复的分类记录:
第一步:先确定每个分类标题对应的保留ID
首先我们需要找出每个cat_title对应的第一条记录的cat_id(也就是你要保留的那条),可以用下面的查询先确认结果是否符合预期:
SELECT cat_title, MIN(cat_id) AS keep_cat_id FROM categories GROUP BY cat_title;
这个查询会返回每个分类标题对应的最小cat_id(也就是最早创建的那条记录的ID),对应你示例里的green对应1、red对应2,完全符合你的需求。
第二步:更新tagging表,修正关联的分类ID
接下来我们要把tagging表中所有指向重复分类ID的记录,更新为对应的保留ID。这里提供两种写法,适配不同场景:
写法一(用窗口函数,MySQL 5.7+支持)
UPDATE tagging t JOIN ( SELECT cat_id, MIN(cat_id) OVER (PARTITION BY cat_title) AS keep_cat_id FROM categories ) c ON t.tagging_cat_id = c.cat_id SET t.tagging_cat_id = c.keep_cat_id WHERE t.tagging_cat_id != c.keep_cat_id;
写法二(用子查询关联,兼容性更强)
UPDATE tagging t JOIN categories c1 ON t.tagging_cat_id = c1.cat_id JOIN ( SELECT cat_title, MIN(cat_id) AS keep_cat_id FROM categories GROUP BY cat_title ) c2 ON c1.cat_title = c2.cat_title SET t.tagging_cat_id = c2.keep_cat_id WHERE t.tagging_cat_id != c2.keep_cat_id;
执行完这个更新后,你可以查询tagging表确认所有关联的ID都已经指向了要保留的分类记录,和你期望的结果一致。
第三步:删除categories表中的重复记录
现在关联数据已经修正完毕,就可以安全删除重复的分类记录了:
DELETE c1 FROM categories c1 JOIN ( SELECT cat_title, MIN(cat_id) AS keep_cat_id FROM categories GROUP BY cat_title ) c2 ON c1.cat_title = c2.cat_title WHERE c1.cat_id != c2.keep_cat_id;
这条语句会删除所有cat_id不等于对应分类标题保留ID的记录,只留下每个分类的第一条记录。
重要注意事项
- 执行前一定要备份数据:不管操作看起来多简单,先备份
categories和tagging表,避免出错无法恢复。 - 添加唯一约束防止后续重复:等你清理完数据后,记得给
categories表的cat_title字段添加唯一约束,从根源上防止重复数据产生:ALTER TABLE categories ADD UNIQUE INDEX idx_unique_cat_title (cat_title); - 定期执行脚本:在你找到重复数据产生的根源之前,可以把这三步SQL做成定时任务(比如用MySQL事件或者系统的定时任务工具)定期运行,保持数据干净。
验证示例
用你提供的示例数据测试的话,执行完上述步骤后:
- Categories表会只剩下
cat_id为1、2、3、7的记录 - Tagging表中所有指向4、5、6的
tagging_cat_id都会被更新为1、1、2,和你期望的结果完全一致
内容的提问来源于stack exchange,提问作者biscuitstack
相关产品推荐
相关产品推荐

