首页 文章

SQLite:删除重复项但保留一个和非重复的字段

提问于
浏览
0

我已经完成了一些研究,发现像_40485这样的帖子有效,除了它删除除了其中一个副本之外的所有行 .

我的表结构是这样的:

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
);

这可能吗?

2 回答

  • 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 值将导致没有行被删除 - 即使对于真正的重复项也是如此 .

    由于这种反直觉行为,请使用直接比较或 NOT EXISTS .

  • 1

    假设您总是希望保留最小的 id 重复项:

    DELETE
    FROM media_items
    WHERE id NOT IN (SELECT MIN(id) FROM media_items GROUP BY hints);
    

    上面的子查询为每组提示(可能只是一个提示)找到该组的最小 id . 然后删除查询将删除最小 id ,而删除所有其他查询 .

相关问题