MYSQL重复数据删除并删除具有最少数据的重复行

时间:2013-08-01 09:16:11

标签: mysql

我正在开发一个MYSQL数据库,该数据库包含以下三列:电子邮件,姓名,姓氏。

我需要做的是重复删除我知道可以使用此功能的电子邮件(此查询仅用于排序不删除):

select distinct emails, name, surname from emails;

select emails, name, surname from emails group by emails having count(*) >= 2;

但是,我还需要确保当发现重复的电子邮件地址时,保留的地址是具有姓名和/或姓氏值的地址。

例如:

| id |电子邮件|名字|姓氏| | 1 | bob@bob.com |鲍勃|保尔森|
| 2 | bob@bob.com | | |

在这种情况下,我想保留第一个结果并删除第二个结果。

我一直在研究使用'case'或'if'语句但是没有使用它们的经验。我尝试用这些语句扩展上述功能,但无济于事。

有人能指出我正确的方向吗?

PS:表中的第一列是自动递增的id值,如果有帮助

更新1:到目前为止@Bohemian的答案工作得很好,但在一个案例中有一个重复的电子邮件地址失败,在一行中它有一个名字但没有姓氏,在下一行它没有名字但有一个姓。它将保留两个记录。所有需要编辑的都是这两个记录中的一个被删除,无论哪个。

更新2:@波希米亚人的答案很棒,但经过更多测试后,我发现它有一个根本性的缺陷,它只有在有一个重复的电子邮件行时,名称和姓氏字段才有数据(如第一个)在上表中输入)。如果有重复的电子邮件但没有任何行同时填写了名称和姓氏字段,则所有这些行都将被忽略而不进行重复数据删除。

此查询的最后一步是找出如何删除不符合当前必要条件的重复项。如果一行只有名字而另一行只是姓氏,那么删除哪一行并不重要,因为电子邮件是最重要的事情。

3 个答案:

答案 0 :(得分:4)

使用mysql multiple-table delete syntax

这很容易
delete b
from mytable a
join mytable b
  on a.email = b.email
  and a.id != b.id
where a.name is not null
and a.surname is not null

答案 1 :(得分:4)

您可以使用此DELETE查询,该查询是通用的,可以轻松调整以支持更多字段:

DELETE tablename.*
FROM
  tablename LEFT JOIN (
    SELECT MIN(id) min_id
    FROM
      tablename t INNER JOIN (
        SELECT
          emails, MAX((name IS NOT NULL) + (surname IS NOT NULL)) max_non_nulls
        FROM
          tablename
        GROUP BY
          emails) m
      ON t.emails=m.emails
         AND ((t.name IS NOT NULL) + (t.surname IS NOT NULL))=m.max_non_nulls
    GROUP BY
      t.emails) ids
  ON tablename.id=ids.min_id
WHERE
  ids.min_id IS NULL

请参阅小提琴here

此查询返回每封电子邮件的最大非空字段数:

SELECT
  emails,
  MAX((name IS NOT NULL) + (surname IS NOT NULL)) max_non_nulls
FROM
  tablename
GROUP BY
  emails

然后我使用tablename加入此查询,以获取具有最大非空字段数的每封电子邮件的最小ID:

SELECT MIN(id) min_id
FROM
  tablename t INNER JOIN (
    SELECT
      emails, MAX((name IS NOT NULL) + (surname IS NOT NULL)) max_non_nulls
    FROM
      tablename
    GROUP BY
      emails) m
  ON t.emails=m.emails
     AND ((t.name IS NOT NULL) + (t.surname IS NOT NULL))=m.max_non_nulls
GROUP BY
  t.emails

然后我将删除所有具有此查询未返回ID的行。

答案 2 :(得分:0)

删除包含重复电子邮件ID的记录

delete 
    from duplicate_email where id in(
        select id from (
            select id, email from duplicate_email group by email having count(id) > 1) as id
    )

但是有一个问题是你可以删除那些只有一个重复邮件的记录,即两个相同的电子邮件,但如果有三个或更多,你可以重复这个查询,直到你删除零记录