【问题标题】:Remove rows with duplicate primary compound key删除具有重复主复合键的行
【发布时间】:2015-07-07 04:26:32
【问题描述】:

我有一个包含以下整数列的表:

group_id, person_id, sequence

理想情况下,主键是(group_id, person_id),但我需要先删除一些重复项。每当有重复时,我只想保留最低的序列值。

我想出了一个查询来选择一些错误的行,但它只获取重复集中的最高序列号。

SELECT COUNT(*) AS num, group_id, person_id, MAX(sequence)
FROM my_table
GROUP BY group_id, person_id
HAVING COUNT(*) > 1;

我确定我错过了一些简单的东西。有没有一种简单的方法可以删除这些重复项?

谢谢。

【问题讨论】:

  • 你试过用 MIN(sequence) 代替 MAX(sequence) 吗?
  • 我有,但它似乎没有做任何有用的事情。它给了我想要保留的行。

标签: mysql duplicate-removal compound-key


【解决方案1】:

尝试编写一个返回要删除的行的查询。假设(group_id,person_id,sequence) 的组合是唯一的,并且您没有 NULL 值...

 SELECT t.* 
   FROM my_table t
   JOIN ( SELECT o.group_id
               , o.person_id
               , MAX(o.sequence) AS max_sequence
            FROM my_table o
           GROUP BY o.group_id, o.person_id
          HAVING COUNT(*) > 1
        ) d
    ON d.group_id      = t.group_id
   AND d.person_id     = t.person_id
   AND d.max_sequence  = t.sequence

我们可以通过将SELECT 关键字替换为DELETE 关键字来将其转换为DELETE 语句。

或者,当我使用与此类似的语句删除行时,我通常会创建一个表作为我要删除的行的“备份”。

只需在 SELECT 前面加上 CREATE TABLE some_new_table_name AS。

然后,我们可以在 DELETE 查询中引用“已保存”的行

DELETE t.*
  FROM my_table t
  JOIN some_new_table_name d
    ON d.group_id      = t.group_id
   AND d.person_id     = t.person_id
   AND d.max_sequence  = t.sequence

这种方法只会得到“一个”重复项。如果原始查询的计数值大于 2,那么我们需要重复此操作足够多次,每次删除最高的序列值,重复此操作直到没有大于 1 的计数值。

如果要删除大量重复项,我们可以使用稍微不同的模式一举将它们删除。

我们可以返回MIN(sequence),我们想要保留的行,而不是返回MAX(sequence)(我们要删除的行)。我们会改变谓词,

    AND d.max_sequence  = t.sequence

成为

    AND d.min_sequence  <> t.sequence

因此,我们删除了该group_id, person_id 的所有 行,但具有最小值的行除外。

我强烈建议您先将其写为SELECT,然后再将其转换为DELETE 语句。而且我还建议您对要删除的行进行良好的备份和/或“保存”副本。以防万一您需要恢复一些行。

【讨论】:

    【解决方案2】:

    所有列都应重复。所以分组应用所有这样的列

    select * from my_table where not EXISTS (
        SELECT group_id, person_id, min(sequence)
        FROM my_table
        GROUP BY group_id, person_id
        HAVING COUNT(*) > 1);
    

    【讨论】:

    • 不,sequence 使行唯一,但 group_id 和 person_id 是重复的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-19
    • 2017-02-12
    • 2019-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-14
    相关资源
    最近更新 更多