想要精通算法和SQL的成长之路 - 删除重复的电子邮箱(SQL)
前言
一. 删除重复的电子邮箱
原题链接
有一张Person
表:
编写一个SQL删除语句来删除所有重复的电子邮件,只保留一个id
最小的唯一电子邮件。
1.1 子查询(中间表相关知识点)
首先,我们可以去考虑如何拿到每种邮件最小id
值:那么我们就需要用到group by 邮件
以及min(id)
:
select min(p.id) as d_id from Person p group by p.email
结果如下(数据量大的话会更直观一点):
之那么既然我们要保留这个数据,那么删除的时候,只需要反过来即可。删除不在上述返回结果集中的数据即可,即not in
:
DELETE from Person where id not in (select min(p.id) as d_id from Person p group by p.email)
但是这么写却有一个问题:
意思是不能先select
出同一表中的某些值,再update
这个表。即不能依据某字段值做判断再来更新某字段的值。
因此对于这种SQL
,需要用到中间表来做查询,上述SQL
修改为:
DELETE from Person where id not in (
select d_id from (
select min(p.id) as d_id from Person p group by p.email
) t1
)
1.2 自连接
自连接的方式很直白:
DELETE p1 FROM Person p1,
Person p2
WHERE
p1.email = p2.email AND p1.id > p2.id
意思是:删除p1
表中的数据,需要删除的数据需要满足下面的条件。
p1
表和p2
表的数据的邮箱一致。p1
表的id
要大于p2
表的id
。
那么以p1
表中的第一条数据为例:
在p
2表中没有符合条件的,因为id
为1是最小的,因此该条数据不删除。
再以p1
表中的第二条数据为例:
在p2
表中依旧没有符合条件的。
以p1
表中的第三条数据为例:
它的id
比p2
表中的第一条数据要大,并且邮箱相同,满足条件,删除。
二. 总结
最终结果:
# 方案一
DELETE from Person where id not in (
select d_id from (
select min(p.id) as d_id from Person p group by p.email
) t1
)
# 方案二
DELETE p1 FROM Person p1,
Person p2
WHERE
p1.email = p2.email AND p1.id > p2.id
知识点:不能依据某字段值做判断再来更新某字段的值。 伪代码表示就是:
update / delete xxx where 列 in ( select 列 where 条件)
这个时候需要运用中间表来做一次查询。