题目链接:https://leetcode-cn.com/problems/delete-duplicate-emails/
题目
编写一个 SQL 查询,来删除 Person
表中所有重复的电子邮箱,重复的邮箱里只保留 Id
最小的那个。
+----+------------------+
| Id | Email |
+----+------------------+
| 1 | john@example.com |
| 2 | bob@example.com |
| 3 | john@example.com |
+----+------------------+
Id 是这个表的主键。
例如,在运行你的查询语句之后,上面的 Person 表应返回以下几行:
+----+------------------+
| Id | Email |
+----+------------------+
| 1 | john@example.com |
| 2 | bob@example.com |
+----+------------------+
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/delete-duplicate-emails
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解答
一开始觉得很简单啊,用 group by
就能解决问题,不过可能题目没说清楚,用 group by
提交一直不通过,本地测试是可以的,估计是必须要求用 delete
进行操作,而不是 select
。
---- MySQL ----
select min(Id) as Id,
Email
from Person
group by Email; -- 简单 只是不通过
参考官方答案之后的解答。
使用 delete
和 where
子句进行解答。
---- MySQL ----
# Write your MySQL query statement below
delete a from Person a,
Person b
where a.Email = b.Email
and a.Id > b.Id ---- 707ms
对MySQL
还是不熟悉,语法跟oracle
还是有一定的差别。
如果表名用了别名,delete后要加别名。
用 left join
试试看。
---- MySQL ----
delete a from Person a
left join Person b
on a.Email = b.Email
where a.Id > b.Id; ---- 726ms
通过 delete
+ 子查询,效率更高。
---- MySQL ----
delete from Person
where Id not in
(
select Id
from
(
select min(Id) as Id
from Person
group by Email
) b
); ---- 506ms
加多一层 select
是因为 delete
和 select
不能同时对一个表进行操作,所以添加一层外查询之后会生成一个临时表,这样子就可以进行 delete
操作了。
思考
通过自连接之后,判断2个id的大小,再进行删除。
对 delete
操作还是比较陌生,毕竟平时用的比较多还是 select
操作,只需要查询数据,就ok。