对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(*)
三者区别:
COUNT(*)
包含所有变量(列)的计数,可以等价为行数。计数过程中不会忽略NULL
COUNT(1)
是一个忽略列本身属性和特点的计数,计数过程中也不会忽略NULL
COUNT(Email)
针对于特定列NULL
而执行效率上:
- 如果表格只有一列:
COUNT(*)
最好- 如果表格有多列:
(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)
网友评论