LeetCode 196. 删除重复的电子邮箱
题目描述


题意分析
直接删除
Person表中重复邮箱的记录,让每种邮箱最终只保留id最小的一行。题目要求修改表内容,不能只查询去重后的结果。
id是唯一标识。对任意一行来说,只要同一邮箱还存在更小的id,它就不是应该保留的记录。
解法:自连接删除非最小记录
核心思路
[!blue]
用
p1、p2两个别名引用同一张表。把p1看作待判断是否删除的记录,把p2看作证明它不是最小记录的同伴。连接条件同时要求
p1.email = p2.email和p1.id > p2.id:前者保证两行属于同一邮箱组,后者保证p1确实有一个更小的同组记录。DELETE p1则明确只删除匹配中的目标侧。组内最小
id找不到更小的同组记录,因此不会匹配删除条件;每个其他记录至少能与这个最小记录匹配一次,因此全部被删除。这样,每种邮箱恰好留下最小id的一行。同一条
p1可能匹配多个更小的p2,但这些匹配都指向同一条待删记录,并不会改变删除结果。无需先把邮箱聚合成一行,也无需依赖记录的物理顺序。
解题步骤
- 给
Person表分别起别名p1、p2,构造自连接。- 用邮箱相同限定同一组,再用
p1.id > p2.id找出存在更小同伴的p1。- 在
DELETE后指定别名p1,删除这些非最小记录;没有重复邮箱的行自然不会被匹配。
代码实现
-- DELETE 后的 p1 指定删哪一侧;自连接找出「存在更小同伴」的行。
DELETE p1
FROM Person AS p1
JOIN Person AS p2
ON p1.email = p2.email
-- 存在更小的同邮箱记录时,才删除目标侧这一行。
AND p1.id > p2.id;
复杂度分析
设记录数为
n,实际执行成本取决于数据库的索引、连接方式和删除计划。
- 时间复杂度:朴素自连接最坏为 $O(n^2)$;当大量记录属于同一邮箱时,也可能产生平方量级的匹配。合适的索引可以减少查找成本,但不能仅凭这段 SQL 断言固定的执行复杂度。
- 空间复杂度:由连接缓冲和待删行记录方式决定;逻辑上存在很多匹配,不代表数据库一定会同时保存全部匹配行。
关键点总结
[!green]
- 删除条件是“存在同邮箱且
id更小的记录”,直接排除非最小者。- 最小记录没有可匹配的更小同伴,天然得到保留。
DELETE p1指定目标侧,别名只是对同一张表中不同记录的引用。
易错点总结
[!yellow]
- 把大于写成小于:会删除较小的记录,最终留下最大
id。- 用不等于替代大于:同组的不同记录会互相匹配,可能把整个重复组删掉。
- 漏掉邮箱相等条件:会把其他邮箱中较小的
id也当作删除依据。- 删除
p2而不是p1:目标方向反了,应该删除有更小同伴的较大记录。- 只写
SELECT DISTINCT:得到查询结果并不等于删除了表中的重复记录。
相似题目
| 题目 | 难度 | 关联与区别 |
|---|---|---|
| 182. 查找重复的电子邮箱 | 简单 | 先识别重复邮箱的分组,本题进一步只保留每组最小id并删除其他行。 |
| 178. 分数排名 | 中等 | 同样区分分组内记录次序与相同值,本题按id选择唯一保留行,不能仅按邮箱值去重后丢失身份。 |
转载与许可
许可
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!