我正在使用具有以下三列的MYSQL数据库:电子邮件,姓名,姓氏。
我需要做的是对电子邮件重复数据删除,我知道可以在其中使用此功能(此查询只是为了排序而不是删除):
select distinct emails, name, surname from emails;
Run Code Online (Sandbox Code Playgroud)
要么
select emails, name, surname from emails group by emails having count(*) >= 2;
Run Code Online (Sandbox Code Playgroud)
但是,我还需要确保当发现重复的电子邮件地址时,保留的是具有名称和/或姓氏值的电子邮件地址。
例如:
| id | 电子邮件| 名称| 姓|
| 1 | bob@bob.com | 鲍勃 保罗|
| 2 | bob@bob.com | | |
在这种情况下,我想保留第一个结果并删除第二个结果。
我一直在研究使用“ case”或“ if”语句,但是对使用这些语句没有经验。我尝试使用这些语句扩展上述功能,但无济于事。
有人能指出我正确的方向吗?
PS:表中的第一列是自动递增的id值,以防
更新1:到目前为止,下面的@Bohemian答案有效,但在一种情况下失败,即重复的电子邮件地址在其中一行中有一个名字但没有姓氏,而在下一行中它没有名称但有姓氏。它将保留两个记录。所有需要编辑的就是无论哪一条记录都将被删除。
更新2:@Bohemian的答案很好,但经过更多测试,我发现它有一个根本性的缺陷,即只有当重复的电子邮件行中名称和姓氏字段具有数据(例如上表)。如果电子邮件重复,但没有任何行同时填写名称和姓氏字段,则所有这些行都将被忽略并且不会重复数据删除。
该查询的最后一步是弄清楚如何删除不符合当前必要条件的重复项。如果其中一行仅包含姓名,另一行仅包含姓氏,那么删除哪一行实际上并不重要,因为保留电子邮件是重要的事情。
您可以使用此 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
Run Code Online (Sandbox Code Playgroud)
请参阅此处的小提琴。
此查询返回每封电子邮件的最大非空字段数:
SELECT
emails,
MAX((name IS NOT NULL) + (surname IS NOT NULL)) max_non_nulls
FROM
tablename
GROUP BY
emails
Run Code Online (Sandbox Code Playgroud)
然后,我将此查询与表名连接起来,以获取具有最大非空字段数的每封电子邮件的最小 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
Run Code Online (Sandbox Code Playgroud)
然后我删除所有具有此查询未返回的 ID 的行。
| 归档时间: |
|
| 查看次数: |
5598 次 |
| 最近记录: |