【问题标题】:How do I delete duplicate rows and keep the first row?如何删除重复行并保留第一行?
【发布时间】:2011-08-31 11:39:49
【问题描述】:

我犯了一个错误,我有不需要的重复项。

我有一个包含 4 个关键字段的表。 A1k1k2k3

A1 是自增和主键。

k1k2k3 的组合应该是唯一的,我必须在创建唯一索引之前删除重复的行。有些行有一个重复,有些有很多。

SELECT CONCAT(k1, k2, k) AS dup_value
  FROM myviews
 GROUP BY dup_value
HAVING (COUNT(dup_value) > 1)

显示我需要处理的重复值。但是现在我不知道如何保留一个并删除每个重复集的其余部分。

【问题讨论】:

  • 关于这个问题有很多问题。这应该作为重复关闭 - 快速。搜索“删除重复行”。这是我的the first result
  • @rockerest 有趣的是,我尝试了您首先链接的解决方案,但它不适用于 MySQL。 OMG Ponies 的回答在 MySQL 上确实对我有用,所以这就是我的 +1 所在。

标签: mysql sql sql-delete


【解决方案1】:

你可以创建一个相同结构但为空的新表,然后在其上创建唯一键,然后将INSERT IGNORE/SELECT * FROM原表插入新表,然后删除原表。

INSERT IGNORE 将自动忽略任何主键或唯一键问题并跳过重复项。

【讨论】:

  • 对于生产系统来说不是一种理想的做法——查询将依赖于旧表,并且数据库中不能有多个同名表。这将需要中断。
  • 非常正确。由于更改键和删除大量行,我认为 OP 尚未投入生产,但我不应该假设!
【解决方案2】:

您需要在 concat 函数中使用分隔符,否则“a”、“b”和“cd”与“abcd”、“”、“”相同。

【讨论】:

    【解决方案3】:

    像这样?

    DELETE FROM myviews WHERE EXISTS(SELECT CONCAT(k1, k2, k) AS dup_value
    FROM myviews
    GROUP BY dup_value
    HAVING (COUNT(dup_value) > 1));
    

    【讨论】:

    • 或者我误解了你的问题。一个元组内是否存在重复性?
    • 这是错误的(至少相对于问题而言),因为它删除了重复集上的所有行
    • 除了删除所有行而不是除一个之外的所有行(正如@LuisSiquot 提到的那样),这将在表上运行时导致错误:SQL 错误(1093):您无法指定目标表'mytable ' 用于 FROM 子句中的更新
    【解决方案4】:

    备份您的数据,然后...

    MySQL supports JOINs in DELETE statements。如果您想保留第一个重复项:

    DELETE a
      FROM MYVIEWS a
      JOIN (SELECT MIN(t.a1) AS min_a1, t.k1, t.k2, t.k3
              FROM MYVIEWS t
          GROUP BY t.k1, t.k2, t.k3
            HAVING COUNT(*) > 1) b ON b.k1 = a.k1
                                  AND b.k2 = a.k2
                                  AND b.k3 = a.k3
                                  AND b.min_a1 != a.a1
    

    如果您想保留最后一个副本:

    DELETE a
      FROM MYVIEWS a
      JOIN (SELECT MAX(t.a1) AS max_a1, t.k1, t.k2, t.k3
              FROM MYVIEWS t
          GROUP BY t.k1, t.k2, t.k3
            HAVING COUNT(*) > 1) b ON b.k1 = a.k1
                                  AND b.k2 = a.k2
                                  AND b.k3 = a.k3
                                  AND b.max_a1 != a.a1
    

    【讨论】:

    • 我收到错误 #1093 - 您无法在 FROM 子句中指定目标表 'myviews' 进行更新
    • @sdfor:抱歉,忘记了这个限制——试试更新的代码。
    猜你喜欢
    • 1970-01-01
    • 2016-10-28
    • 1970-01-01
    • 1970-01-01
    • 2020-07-20
    • 2013-04-08
    • 2023-01-30
    • 2020-03-28
    • 2020-11-10
    相关资源
    最近更新 更多