我遇到了一个问题,即以某种方式重复行已进入数据库,其中某列重复。我进行了一些研究,发现像this one这样的帖子可以正常工作,只是它删除了除重复项之一以外的所有行。
我的表结构如下:
id | hints |
208 episode=1&season=1&show=Name1
209 episode=1&season=1&show=Name1
210 episode=1&season=2&show=Name1
211 episode=1&season=2&show=Name1
212 episode=3&season=3&show=Name2
如您所见,行ID 208和209是彼此的重复,而行210和211也是彼此的重复。但是,212存在,并且不能与其他任何行重复。
我已经可以通过运行以下查询来识别重复项:
SELECT id, hints FROM media_items GROUP BY hints HAVING count(*) > 1;
我的表有21097行,上面的查询返回2309个重复项。如果我运行从上面的链接获得的以下查询,则将删除除2309个重复项之外的所有行,这与我要执行的操作相反。
DELETE from media_items
WHERE rowid NOT IN (
SELECT min(rowid) FROM media_items GROUP BY hints HAVING count(*) > 1
);
我认为该解决方案在技术上适用于要求它的用户,因为他们不需要保留一些不包含重复项的行。
我还尝试了以下查询,这对我来说很有意义(我很容易误解),但它一次只能删除1行,如果我不厌其烦地运行它,便会重复两次(2309) ,它实际上会更进一步,并开始删除非重复项。
DELETE FROM 'media_items'
WHERE id = (
SELECT MIN(id) FROM 'media_items' GROUP BY hints HAVING COUNT(*) > 1
);
这可能吗?
答案 0 :(得分:1)
假设您始终要保留重复项中最小的id
:
DELETE
FROM media_items
WHERE id NOT IN (SELECT MIN(id) FROM media_items GROUP BY hints);
上面的子查询为每组提示(可能只是一个提示)找到了该组的最小id
。然后,删除查询将保留最小的id
,而其他所有查询将被删除。
答案 1 :(得分:0)
如果您要删除重复的所有行,则:
DELETE FROM media_items
WHERE EXISTS (SELECT 1
FROM media_items mi2
WHERE mi2.hint = media_items.hint AND mi2.id <> media_items.id
);
如果您想保留重复项中的某一行,请说 ID最小的那个,我建议一个相关子查询:
DELETE FROM media_items
WHERE id > (SELECT MIN(mi2.id)
FROM media_items mi2
WHERE mi2.hint = media_items.hint
);
我强烈建议您不要对子查询使用NOT IN
。在这种情况下,我应该工作,因为我怀疑id
可能是NULL
。但是子查询返回的单个NULL
值将导致删除 no 行-即使对于真正的重复项也是如此。
由于这种违反直觉的行为,请使用直接比较或NOT EXISTS
。