【Leetcode】高频SQL基础题--196.删除重复的电子邮箱
【Leetcode】高频SQL基础题–196.删除重复的电子邮箱
要求:编写解决方案 删除 所有重复的电子邮件,只保留一个具有最小 id 的唯一电子邮件。
(对于 SQL 用户,请注意你应该编写一个 DELETE 语句而不是 SELECT 语句。)
(对于 Pandas 用户,请注意你应该直接修改 Person 表。)
运行脚本后,显示的答案是 Person 表。驱动程序将首先编译并运行您的代码片段,然后再显示 Person 表。Person 表的最终顺序 无关紧要 。
解题思路1:
1、使用内部子查询 SELECT MIN(id) FROM Person GROUP BY email返回每个电子邮件的最小id。然后,外部的 DELETE删除不在这个列表中的id。
解题思路2:
1、使用自连接,对于每个电子邮件,如果存在更小的id(p1.id > p2.id),则删除当前id(p1)。
这直接避免了子查询,性能更好。
代码1:
DELETE FROM Person
WHERE id NOT IN (SELECT min_id FROM (SELECT MIN(id) AS min_idFROM PersonGROUP BY email) AS temp
);
注意:
1、为什么子查询外还要再套一层查询?
为了避免MySQL的“同时查询与更新”错误:
MySQL不允许在一条DELETE(或UPDATE)语句中,同时查询和修改同一张表。内层子查询和外层DELETE操作的都是Person表,这就会触发MySQL的这个限制。所以,将内层查询的结果包装成一个临时的派生表。外层DELETE语句不再直接查询原始表,而是查询这个临时出来的、结果集固定的“表”。
执行逻辑:
1、数据库会先执行最内层的查询 SELECT MIN(id) AS min_id FROM Person GROUP BY email,得到一个包含所有需要保留的最小ID的结果集。
2、然后将这个结果集物化为一个临时的、只在当前查询中存在的派生表,我们给它起名为 temp_table。
3、接着,外层 SELECT min_id FROM temp_table只是从这个临时表中简单地取出所有 min_id,组成一个最终的ID列表。
4、最后,外层的 DELETE语句根据这个最终的ID列表执行删除操作。
代码2:
DELETE p1
FROM Person p1, Person p2
WHERE p1.email = p2.email AND p1.id > p2.id;