Leetcode 182. 查找重复的电子邮箱

原题题目

表: Person

+-------------+---------+
| Column Name | Type    |
+-------------+---------+
| id          | int     |
| email       | varchar |
+-------------+---------+
id 是该表的主键(具有唯一值的列)。
此表的每一行都包含一封电子邮件。电子邮件不包含大写字母。

编写解决方案来报告所有重复的电子邮件。 请注意,可以保证电子邮件字段不为 NULL。

以 任意顺序 返回结果表。

结果格式如下例。

示例 1:

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

思考解决方案

首先,我们来分析下这个问题的几个关键点:

  1. 重复的定义:我们并不关心 id 这个字段,重点是 email 字段。所以,只要电子邮件出现了两次或更多次,就算是重复。

  2. 结果要求:我们返回的结果只需要包含 email,而且可以不按特定的顺序。

好了,问题就是这么简单了!但是要怎么解决呢?让我给你展示几个方法,从简单到高阶,我们一起来看看吧!

一、使用 GROUP BYHAVING

这是最常见的解决方式,利用 SQL 的分组功能。首先,我们按照 email 对数据进行分组,然后使用 HAVING 子句来筛选出出现次数大于 1 的电子邮件。

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

解释:

  • GROUP BY email:这会将相同的电子邮件分成一组。

  • HAVING COUNT(*) > 1:我们用 HAVING 来过滤出那些出现次数超过 1 次的电子邮件。

注意:使用GROUP BY进行分组之后,如果需要过滤只能使用HAVING,而不可以使用where

二、使用 JOIN 来查找重复

虽然我们不常用,但这也是一种非常有趣的解决方法。这里我们使用自连接(Self Join)来实现,连接 Person 表的两份数据并查找那些有相同 email 的行。

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

解释:

  • JOIN Person p2 ON p1.email = p2.email AND p1.id != p2.id:这里我们把 Person 表与它自己连接,条件是 email 相同,但是 id 不相同,这样就能找到重复的电子邮件。

  • DISTINCT:我们使用 DISTINCT 来去重,避免重复的电子邮件被多次显示。

这种方法看似复杂,但它利用了 SQL 中的连接操作,非常灵活。它的原理是通过对同一张表进行“自我联接”来查找重复。

三、 使用 WINDOW 函数(高级方法)

对于喜欢挑战 SQL 的高级技巧的人,可以考虑使用 WINDOW 函数。这个方法适用于支持窗口函数的数据库(例如 MySQL 8.0 及以上版本)。通过 COUNT() 窗口函数来对每个电子邮件进行计数。

SELECT email
FROM (
    SELECT email, COUNT(*) OVER (PARTITION BY email) AS email_count
    FROM Person
) AS email_counts
WHERE email_count > 1;

注意:这也是一种创建临时表的方式,还可以用以下的方式实现

select Email from
(
  select Email, count(Email) as num
  from Person
  group by Email
) as statistic
where num > 1
;

四、总结

方法时间复杂度空间复杂度适用场景
方法 1 GROUP BY + HAVINGO(N)O(N)推荐使用,最常见且高效
方法 2 JOINO(N^2)O(N^2)不推荐大数据集,性能差
方法 3 WINDOW 函数O(N)O(N)性能高,适合大数据集,支持窗口函数时推荐
大数据集推荐方案:

对于大数据集,方法 1(GROUP BY + HAVING方法 3(WINDOW 函数) 是最优选择。GROUP BY 已经经过多年的优化,可以高效处理大多数查询。而 WINDOW 函数在计算上通常更为高效,尤其在数据量大时能够避免额外的分组操作。

总之,选择合适的方法不仅依赖于 SQL 本身的优化,还需要考虑数据库的硬件配置和处理能力。对于大数据集,尽量避免使用 JOIN,因为它的性能开销非常大。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值