关注
文末的名片达文汐
,回复关键词“力扣源码”,即可获取完整源码!!详见:源码和核心代码的区别
题目详情
表: Person
Column Name | Type |
---|---|
id | int |
varchar |
id
是该表的主键列(具有唯一值的列)。该表的每一行包含一封电子邮件。电子邮件将不包含大写字母。
编写解决方案删除所有重复的电子邮件,只保留一个具有最小id
的唯一电子邮件。(对于 SQL 用户,请注意你应该编写一个DELETE
语句而不是SELECT
语句。)
运行脚本后,显示的答案是Person
表。驱动程序将首先编译并运行您的代码片段,然后再显示Person
表。Person
表的最终顺序无关紧要。返回结果格式如下示例所示。
示例 1:
输入: Person 表:
id | |
---|---|
1 | john@example.com |
2 | bob@example.com |
3 | john@example.com |
输出:
id | |
---|---|
1 | john@example.com |
2 | bob@example.com |
解释: john@example.com重复两次。我们保留最小的Id = 1。
解题思路
- 核心目标:删除重复的电子邮件,只保留每个重复电子邮件组中id最小的记录。
- 关键步骤:
- 找出每个电子邮件对应的最小id(即需要保留的记录)。
- 删除那些id不在最小id集合中的重复记录。
- 技术难点:MySQL不允许在DELETE的子查询中直接引用正在更新的表。
- 解决方案:
- 使用子查询先获取每个email分组的最小id,并将结果作为临时表。
- 在DELETE语句中通过临时表判断需要删除的记录(id不在最小id集合中的记录)。
- 优化点:
- 使用分组查询(GROUP BY email)高效获取最小id。
- 通过临时表绕过MySQL的限制,避免表锁定和性能问题。
- 直接操作原表,无需额外内存存储中间结果。
代码实现 (MySQL版)
# 删除重复电子邮件,保留最小id的记录
DELETE FROM Person
WHERE id NOT IN (
SELECT t.min_id FROM (
SELECT MIN(id) AS min_id
FROM Person
GROUP BY email
) AS t
);
代码说明
- 子查询逻辑:
- 内层查询:
SELECT MIN(id) FROM Person GROUP BY email
获取每个email分组中的最小id。 - 外层查询:
SELECT t.min_id FROM (...) AS t
将内层查询结果作为临时表t
,避免MySQL的更新限制。
- 内层查询:
- 删除逻辑:
DELETE FROM Person WHERE id NOT IN (...)
删除所有id不在“最小id集合”中的记录。
- 效率保障:
- 分组查询(GROUP BY)利用索引(若有)高效计算最小id。
- 临时表仅存储最小id集合,内存占用低。
- 全表扫描一次完成删除,执行效率高。