美文网首页
[SQL] LeetCode题解 #182 查找重复的电子邮箱

[SQL] LeetCode题解 #182 查找重复的电子邮箱

作者: 半为花间酒 | 来源:发表于2020-05-05 11:19 被阅读0次

对SQL语句不熟悉欢迎查看我整理的笔记:[SQL] MySQL基础 + python交互

转载请注明:陈熹 chenx6542@foxmail.com (简书号:半为花间酒)
若公众号内转载请联系公众号:早起Python

题目:

简单题 #182

SQL架构:

Create table If Not Exists Person (Id int, Email varchar(255));
Truncate table Person;
insert into Person (Id, Email) values ('1', 'a@b.com');
insert into Person (Id, Email) values ('2', 'c@d.com');
insert into Person (Id, Email) values ('3', 'a@b.com');

题解

第一种解法

—— 基于分组计数

寻找重复的邮箱,可以这么理解:
根据邮箱地址对所有邮箱进行分组,然后判断每个组的个数,正常情况下邮箱是唯一的,则产生的组也是仅含有一个记录,如果超过1个则说明这个邮箱地址有重复

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

这里简单解析一个知识点:COUNT(1) COUNT(Email) COUNT(*) 三者区别:

  1. COUNT(*) 包含所有变量(列)的计数,可以等价为行数。计数过程中不会忽略NULL
  2. COUNT(1) 是一个忽略列本身属性和特点的计数,计数过程中也不会忽略NULL
  3. COUNT(Email) 针对于特定列Email的计数,计数过程中会忽略NULL

而执行效率上:

  1. 如果表格只有一列: COUNT(*) 最好
  2. 如果表格有多列:
    (1) 没有主键:COUNT(1) 的执行效率优于COUNT(*)
    (2) 有主键但不作为计数的列名:COUNT(1) 的执行效率优于COUNT(列名)
    (3) 有主键且作为计数的列名: COUNT(列名) 的执行效率优于COUNT(1)

分析题目中的表格,有两个字段且不存在主键,因此我选择COUNT(1)

如果不用HAVING写出的语句会比较绕,当然也可以达到目的

SELECT Email
FROM (
    SELECT Email, COUNT(1) count 
    FROM person 
    GROUP BY Email) tb1
WHERE COUNT > 1;

第二种解法

—— 基于JOIN自连接

另外一种思路是自连接,以Email作为连接字段
核心语句是Id不相等作为过滤条件,对筛选出的Email去重也可以得出答案

SELECT DISTINCT(tb1.Email) 
FROM Person tb1 JOIN Person tb2 
ON tb1.Email = tb2 .Email AND tb1.Id != tb2 .Id;

在SQL中 != 还可以写作 <>,故还可以写成

SELECT DISTINCT(tb1.Email) 
FROM Person tb1 JOIN Person tb2 
ON tb1.Email = tb2 .Email AND tb1.Id <> tb2 .Id;

第三种解法

—— 基于NOT IN的子查询

SQL中还有一个重要的判断:NOT IN
因此还有一种思路:根据Email分组,选出各组最小的Id,如果存在重复值,则有些Id无法被选中,将这部分的查询作为WHERE的子查询,用Id NOT IN 子查询Id最后对Email去重即可

SELECT DISTINCT(Email) 
FROM Person
WHERE Id NOT IN (
    SELECT MIN(Id) Id 
    FROM Person  
    GROUP BY Email)

相关文章

网友评论

      本文标题:[SQL] LeetCode题解 #182 查找重复的电子邮箱

      本文链接:https://www.haomeiwen.com/subject/zznpghtx.html