LeetCode 182. 查找重复的电子邮箱
题目描述


题意分析
Person中id唯一,但这里需要统计的是每个邮箱的记录数,而不是每条记录的信息。因此先把相同
解法:SQL 分组统计
核心思路
[!blue]
GROUP BY email把邮箱相同的记录归为一组。每组对应一个候选邮箱,COUNT(*)统计该组包含多少行;HAVING COUNT(*) > 1则把只出现一次的组排除。可以按逻辑处理顺序理解:先从
Person取得原始记录,再分组和计数,然后用HAVING筛选组,最后输出每组的邮箱。WHERE过滤的是分组前的单行,此时尚没有组内总数,因此不能用它来写当前聚合条件。分组结果已经是每个邮箱一行,投影
email AS Email就满足结果格式,无需再次使用DISTINCT。
解题步骤
- 查询
Person,按id分组。- 用
COUNT(*)统计每组记录数,以HAVING保留大于 1 的组。- 选择
样例中的
a@b.com对应两行,计数为 2,能够保留;c@d.com只对应一行,被筛掉。空表不会生成任何分组,所有邮箱都不重复时也会自然返回空结果。
代码实现
SELECT email AS Email
FROM Person
GROUP BY email
HAVING COUNT(*) > 1;
复杂度分析
设表有 $N$ 行、不同邮箱有 $U$ 个。以下将单次邮箱比较或哈希的成本视为常数;实际执行计划由数据库决定。
- 时间复杂度:哈希聚合的期望时间为 $O(N)$;若先排序再聚合,则通常为 $O(N\log(N+1))$。已有合适的邮箱索引时,也可能按索引顺序直接聚合。
- 空间复杂度:哈希聚合需要 $O(U)$ 额外空间保存各邮箱计数;排序聚合的内存和临时磁盘用量取决于排序方式。
关键点总结
[!green]
- 分组列决定统计对象:本题统计邮箱,所以分组键是
COUNT(*)统计组内行数;题目保证COUNT(email)也等价。- 筛选聚合值用
HAVING;它判断整个组是否应出现在结果中。- 输出不需要计数列,计数只用于筛选,也不需要额外去重。
易错点总结
[!yellow]
- 在
WHERE中使用COUNT(*):此时还没有分组结果,聚合函数不能这样用于行过滤。- 按
id分组:每个主键只对应一行,永远找不到计数大于 1 的组。- 只写
DISTINCT email:会把只出现过一次的邮箱也输出,无法表达“重复”。- 把阈值写成
>= 1:每个已有分组都满足,必须要求至少两行。- 选择未分组的
id:同一重复邮箱对应多个编号,没有唯一应输出的编号;本题只要求邮箱列。
相似题目
| 题目 | 难度 | 关联与区别 |
|---|---|---|
| 196. 删除重复的电子邮箱 | 简单 | 先识别重复邮箱,再进一步删除重复行;本题只做分组查询,不改变表数据。 |
转载与许可
许可
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!