【问题标题】:SQLite: Remove Duplicates but keep one and non-duplicate fieldsSQLite:删除重复但保留一个和非重复的字段
【发布时间】:2018-12-09 14:53:03
【问题描述】:

我遇到了一个问题,即以某种方式重复的行已进入数据库,其中某个列是重复的。我做了一些研究,发现像 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
); 

这可能吗?

【问题讨论】:

    标签: sql sqlite


    【解决方案1】:

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

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

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

    【讨论】:

    • 感谢您的回复。请再次查看我的帖子,我进行了一些更改。这已经在我的帖子中了,它会删除所有内容,但重复项除外。之后我的表剩下 2309 行,即重复的确切数量。我还需要保留不重复的行。
    • @KeithBlack 我的查询不一样。重新加载您的页面。
    • 啊,我明白了,不管怎样,它仍然具有相同的效果。另一个用户在我投票之前删除了他们的帖子,他能够为我解决这个问题。这有效:DELETE FROM media_items where rowid IN (SELECT min(rowid) FROM media_items GROUP BY hints HAVING count(*) > 1);
    • 我不明白为什么会这样,但如果确实如此,那么也许可以继续使用它。我认为您不应该针对最小行,因为只有其中一个。相反,您需要保留一行,然后删除其余的重复项。
    【解决方案2】:

    如果你想删除所有行重复的,那么:

    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

    【讨论】:

      猜你喜欢
      • 2016-09-18
      • 1970-01-01
      • 1970-01-01
      • 2021-11-29
      • 1970-01-01
      • 2011-08-26
      • 2015-09-27
      • 1970-01-01
      • 2022-07-19
      相关资源
      最近更新 更多