如何删除一条 table 中的重复项,但只保留一条记录?

How to delete duplicates from one table, but keeping only one record?

您好SQL查询专家! 我有一个名为 'mytable' 的 table,它有 2 列,例如 id 和 title 。 我试图删除重复项,但只有一个记录(行)比较标题。 以下是我的选择:

DELETE FROM `myTable` AS `m1`
WHERE `m1`.`id` 
NOT IN (SELECT MIN(`b`.`id`) as `recordid` FROM `myTable` AS `b` GROUP BY `b`.`title`)

错误:Error in query (1064): Syntax error near '* FROM `myTable` AS `m1` WHERE `m1`.`id` NOT IN (SELECT MIN(`b`.`id`) as `reco' at line 1 但我遇到了麻烦,并试图解决这个问题超过 2 小时。 这似乎是一个非常简单的问题。 但我想不通。所以我要求计算器!

主要是,我看到了一些奇怪的东西。 我这样试过,但没有任何错误。

SELECT * FROM `myTable` AS `m1`
WHERE `m1`.`id` 
NOT IN (SELECT MIN(`b`.`id`) as `recordid` FROM `myTable` AS `b` GROUP BY `b`.`title`)

当我 运行 这个查询时,我可以从 'myTable' table.

中获取要删除的记录(行)列表

为什么我可以获取到要删除的列表,却出现删除问题?

我真的需要你的帮助。 谢谢大家!

您可以这样表述:

delete m
    from mytable m left join
         (select m2.title, min(m2.id) as min_id
          from mytable m2
          group by m2.title
         ) m2
         on m.title = m2.title and m.id > m.min_id;

为了提高性能,您需要在 (title, id) 上建立索引。

我认为戈登的回答抓住了要点。最近不得不做类似的事情,结果是这样的(适用于您的情况):

DELETE FROM mytable WHERE id IN (
    SELECT *
    FROM (
        SELECT m.id
        FROM my_table m
        WHERE m.id NOT IN (
            SELECT MAX(m.id)
            FROM my_table sub
            GROUP BY sub.title
            HAVING COUNT(sub.title) > 1
        )
        AND m.id NOT IN (
            SELECT MAX(sub2.id)
            FROM my_table sub2
            GROUP BY sub2.title
            HAVING COUNT(sub2.title) = 1
        )
  ) AS m
)

额外的包装器是必要的(如果我没记错的话)因为 sub-query 在 DELETE 语句中是不允许的(但可以像所示那样使用)。

这将按 ID 删除所有计数(title)大于 0 的记录,但不会删除最新的(max)记录。


注意:这是一个非常密集的查询。建议在 ID 和标题上建立索引,即便如此:sloooowwww。 运行 这仅需要 10 万条带索引的记录,但仍需要大约 10 秒。

语法:

DELETE FROM `myTable` AS `m1`

错了。
应该是:

DELETE m1 FROM `myTable` AS `m1`

但您不需要为 table 添加别名,您可以这样做

DELETE FROM `myTable`

此外 MySql 不允许在子查询中直接使用目标 table,就像您使用 NOT IN 一样,但是您可以通过包含子查询来克服此限制在另一个里面:

DELETE FROM `myTable` 
WHERE `id` NOT IN (
  SELECT `recordid`
  FROM (
    SELECT MIN(`id`) as `recordid` 
    FROM `myTable` 
    GROUP BY `title`
  ) t  
)

我删除了嵌套子查询的别名,因为不需要它们。

我终于找到了问题的确切原因。 我引用了@Malakiyasanjay 的评论。 你可以从这里找到 How to keep only one row of a table, removing duplicate rows?

我这样试过:(它对我也有效,但是 运行 查询 30,000 行花了很多时间)

delete from myTable
where id not in 
(select min(id) as min from (select * from myTable) as x group by title)

问题是我无法将“myTable”table 指定为目标 table。所以我使用 (select * from myTable) as x 并弄明白了。

抱歉,我无法解释更多细节,因为我不熟悉 mysql 查询。但你应该注意:

MySql does not allow the direct use of the target table inside a subquery like the one you use with NOT IN, but you can overcome this limitation by enclosing the subquery inside another one. (Please reference @forpas 's answer.)

但是你要注意这需要很长时间...这可能会导致超时错误。我 运行 这个关于 table 的查询有大约 600,000 行,但几天没有响应。所以我得出结论,这个想法非常适合小型数据库 table.

希望对大家有所帮助! :)