Article / 文章

LeetCode 第182题:查找重复的电子邮箱

表: Person +-------------+---------+ | Column Name | Type | +-------------+---------+ | id | int | | email | varchar | +-------------+---------+ id 是该表的主键列。 该表的每一行包含一个电子邮件。电子邮件将不包含大

题目描述

表: Person

+-------------+---------+
| Column Name | Type    |
+-------------+---------+
| id          | int     |
| email       | varchar |
+-------------+---------+
id 是该表的主键列。
该表的每一行包含一个电子邮件。电子邮件将不包含大写字母。

编写一个 SQL 查询来报告所有重复的电子邮件。

注意,可以以任何顺序返回结果表。

难度

简单

题目链接

点击在LeetCode中查看题目

示例

示例 1:

输入: 
Person 表:
+----+---------+
| id | email   |
+----+---------+
| 1  | a@b.com |
| 2  | c@d.com |
| 3  | a@b.com |
+----+---------+
输出: 
+---------+
| Email   |
+---------+
| a@b.com |
+---------+
解释: a@b.com 出现了两次。

提示

  • 表中的每一行都包含一个有效的电子邮件地址。

解题思路

方法一:使用 GROUP BY 和 HAVING

这道题要求我们找出所有重复的电子邮箱。解决思路是使用 GROUP BY 对电子邮箱进行分组,然后使用 HAVING 筛选出出现次数大于1的电子邮箱。

关键点:

  1. 使用 GROUP BY 按电子邮箱分组
  2. 使用 HAVING 子句筛选出计数大于1的组
  3. 选择电子邮箱作为结果输出

时间复杂度:O(n log n),其中 n 是 Person 表中的行数(排序的时间复杂度) 空间复杂度:O(n)

方法二:使用自连接(Self Join)

另一种解决方法是使用自连接,找出不同id但相同电子邮箱的记录。

关键点:

  1. 使用 Person 表自连接
  2. 匹配条件是相同的电子邮箱但不同的id
  3. 使用 DISTINCT 去除重复结果

时间复杂度:O(n²),其中 n 是 Person 表中的行数(自连接的时间复杂度) 空间复杂度:O(n)

代码实现

SQL 实现(方法一:GROUP BY 和 HAVING)

SELECT email AS Email
FROM Person
GROUP BY email
HAVING COUNT(email) > 1;

SQL 实现(方法二:自连接)

SELECT DISTINCT p1.email AS Email
FROM Person p1
JOIN Person p2 ON p1.email = p2.email AND p1.id != p2.id;

性能分析

各SQL实现的性能对比:

实现方法 执行用时 内存消耗 特点
方法一 350 ms 0B 使用GROUP BY和HAVING,代码简洁高效
方法二 540 ms 0B 使用自连接,直观但性能较差

补充说明

代码亮点

  1. 方法一使用 GROUP BY 和 HAVING,是解决此类问题的标准方法
  2. 方法二使用自连接,虽然性能较差,但思路直观
  3. 两种方法都考虑了结果去重

GROUP BY 与 自连接的比较

在解决此类查找重复值的问题时,GROUP BY 和自连接是两种常用的方法:

GROUP BY 优势

  • 通常执行效率更高,特别是对于大型表
  • 代码更简洁,易于理解
  • 直接得到统计信息

自连接优势

  • 可以获取更多与重复记录相关的信息
  • 在某些复杂场景下更灵活
  • 对于某些数据库引擎可能有优化

对于本题,GROUP BY 方法通常是更好的选择,因为它简洁高效。

常见错误

  1. 忘记在 HAVING 子句中使用 COUNT > 1 条件
  2. 在方法二中忘记加入 p1.id != p2.id 条件,导致自身也被匹配
  3. 忘记使用 DISTINCT 去除重复结果
  4. GROUP BY 语句中的列名写错

相关题目