6

我正在研究一个 MYSQL 数据库,它具有以下三列:电子邮件、姓名、姓氏。

我需要做的是对我知道可以使用诸如此功能的电子邮件进行重复数据删除(此查询只是为了排序而不是删除):

select distinct emails, name, surname from emails;

或者

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

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

例如:

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

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

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

谁能指出我正确的方向?

PS:表中的第一列是自动递增的 id 值,以防万一

更新 1:到目前为止,@Bohemian 的回答效果很好,但在一种情况下失败了,其中有一个重复的电子邮件地址,其中一行有一个名字但没有姓氏,而在下一行它没有名字但有一个姓氏。它将保留这两个记录。需要编辑的只是删除这两条记录中的一条,不管是哪一条。

更新 2:@Bohemian 的答案很棒,但经过更多测试后,我发现它有一个根本缺陷,即它仅在名称和姓氏字段具有数据的重复电子邮件行中有效(如第一个条目)上表)。如果有重复的电子邮件,但没有一行填写姓名和姓氏字段,则所有这些行都将被忽略且不会重复数据删除。

此查询的最后一步是确定如何删除不满足当前必要条件的重复项。如果一行只有姓名,而另一行只有姓氏,那么删除哪一个并不重要,因为电子邮件是要保留的重要内容。

4

3 回答 3

4

这很容易使用 mysql 的多表删除语法

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
于 2013-08-01T10:38:35.473 回答
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

在此处查看小提琴。

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

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 的行。

于 2013-08-01T15:38:49.943 回答
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
    )

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

于 2015-11-28T19:59:38.947 回答