删除重复的行只留下最旧的行?

时间:2010-09-08 20:25:24

标签: mysql duplicate-removal delete-row

我有一个数据表,并且有许多来自用户提交的重复条目。

我想根据字段subscriberEmail删除所有重复行,只留下原始提交。

换句话说,我想搜索所有重复的电子邮件,并删除这些行,只留下原始邮件。

如何在不交换桌子的情况下执行此操作? 我的表包含每行的唯一ID。

3 个答案:

答案 0 :(得分:27)

由于您使用id列作为哪个记录为“原始”的指示符:

delete x 
from myTable x
 join myTable z on x.subscriberEmail = z.subscriberEmail
where x.id > z.id

这将为每个电子邮件地址留下一条记录。

编辑添加:

解释上面的查询...

这里的想法是加入桌子反对自己。假装你有两个表副本,每个副本都有不同的名称。然后,您可以将它们相互比较,并找到最低的ID或每个电子邮件地址。然后,您将看到稍后创建的重复记录,并可以将其删除。 (当我想到这个时,我正在想象Excel。)

为了在表上执行该操作,将其与自身进行比较并能够识别每一方,您使用表别名。 x是表别名。它在from子句中分配,如:from <table> <alias>x现在可以在同一查询的其他位置使用,以将该表称为快捷方式。

delete x使用我们的操作和目标启动查询。我们将执行查询以从多个表中选择记录,并且我们要删除x中显示的记录。

别名用于指代表的两个“实例”。 from myTable x join myTable z on x.subscriberEmail = z.subscriberEmail在电子邮件匹配的地方碰到桌子。如果没有下面的where子句,则会选择每条记录,因为它可以与自身连接。

where子句限制所选的记录。 where x.id > z.id允许'实例'别名x仅包含与电子邮件匹配但具有更高id值的记录。表格中您真正想要的数据,唯一的电子邮件地址(ID最低)不会成为x的一部分,也不会被删除。 x中的唯一记录将是重复记录(电子邮件地址),其具有比该电子邮件地址的原始记录更高的id

在这种情况下,join和where子句可以合并:

delete x 
  from myTable x 
  join myTable z
    on x.subscriberEmail = z.subscriberEmail
      and x.id > z.id

为防止重复,请考虑将subscriberEmail列设为UNIQUE索引列。

答案 1 :(得分:1)

这个怎么样,现在你不必使用自联接创建任何临时表

DELETE u1 FROM users u1, users u2 WHERE u1.id < u2.id AND u1.email = u2.email

检查表格中是否有任何重复记录

SELECT count(*) as Count, email FROM users u group by email having Count > 1

答案 2 :(得分:0)

如果每行都有唯一的ID,您可以尝试这样的方法。不要问我为什么你需要第二个select语句,mysql不会让我执行否则。此外,按任意列分组可使您的结果独一无二。

delete from my_table where id in (
  select id from (
    select id from my_table a group by subscriberEmail having count(*) > 1
  ) b
);