# 图解面试题：如何查找重复数据？

![](https://4109408004-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MTuZ3PxkXf2a7UbRybW%2F-MUhz9BmmT7AltkgZWYm%2F-MUhzWLZQW9L5OPneL3p%2F%E7%AE%80%E5%8D%95%E6%9F%A5%E8%AF%A2_1.jpg?alt=media\&token=a75a9f6e-b589-4dbf-a001-b712b2b16a12)

**【题目】**

编写一个 SQL 查询，查找学生表中所有重复的学生名。

![](https://4109408004-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MTuZ3PxkXf2a7UbRybW%2F-MUhz9BmmT7AltkgZWYm%2F-MUhz_qxNNGEnXQmqQv9%2F%E7%AE%80%E5%8D%95%E6%9F%A5%E8%AF%A2_2.png?alt=media\&token=bf297e9b-f7a4-4b1b-8965-52aa9c4bb8c2)

**【解题思路】**

1. 看到 “找重复” 的关键字眼，首先要用分组函数（group by），再用聚合函数中的计数函数 count()给姓名列计数。
2. 分组汇总后，生成了一个如下的表。从这个表里选出计数大于 1 的姓名，就是重复的姓名。

![](https://4109408004-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MTuZ3PxkXf2a7UbRybW%2F-MUhz9BmmT7AltkgZWYm%2F-MUhzevdrAWPUblz--Gn%2F%E7%AE%80%E5%8D%95%E6%9F%A5%E8%AF%A2_3.jpg?alt=media\&token=0261e6c2-093c-4ffc-8203-2cd1431876be)

**【解题步骤】**

* **方法一**

1）创建一个辅助表，将姓名列进行行分组汇总

```sql
select 姓名, count(姓名) as 计数
from 学生表
group by 姓名;
```

![](https://4109408004-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MTuZ3PxkXf2a7UbRybW%2F-MUhz9BmmT7AltkgZWYm%2F-MUhzhKblOgCskk7RsF2%2F%E7%AE%80%E5%8D%95%E6%9F%A5%E8%AF%A2_4.jpg?alt=media\&token=d0da91a5-156b-4b18-b9bc-09ffaab64269)

2）选出辅助表中计数大于 1 的姓名

```sql
select 姓名 from 辅助表
where 计数 > 1;
```

![](https://4109408004-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MTuZ3PxkXf2a7UbRybW%2F-MUhz9BmmT7AltkgZWYm%2F-MUhzk-nYN-OKnTmUoTQ%2F%E7%AE%80%E5%8D%95%E6%9F%A5%E8%AF%A2_5.jpg?alt=media\&token=da3151bb-5890-407d-9e79-8ac37911880a)

3）结合前两步，将 “创建辅助表” 的步骤放入子查询

```sql
select 姓名 from
(
 select 姓名, count(姓名) as 计数
 from 学生表
 group by 姓名
) as 辅助表
where 计数 > 1;
```

结果：

![](https://4109408004-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MTuZ3PxkXf2a7UbRybW%2F-MUhz9BmmT7AltkgZWYm%2F-MUhzmvD8U4Xm7ROaWcI%2F%E7%AE%80%E5%8D%95%E6%9F%A5%E8%AF%A2_6.jpg?alt=media\&token=d558fb84-2640-4c76-adb1-053fd9995ce6)

* **方法二**

这时候有的同学可能会想，为什么要这么麻烦创建一个子查询，不能用这个语句（将 count 放到 where 字句中）直接得出答案吗？

```sql
select 姓名
from 学生表
group by 姓名
where count(姓名) > 1;
```

如果我们运行下这个 sql 语句，会报下面的错误，问题出在哪里呢？

![](https://4109408004-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MTuZ3PxkXf2a7UbRybW%2F-MUhz9BmmT7AltkgZWYm%2F-MUhzpD7xLpkUkMORGwc%2F%E7%AE%80%E5%8D%95%E6%9F%A5%E8%AF%A2_7.jpg?alt=media\&token=6c18d986-701c-47f2-bbd6-a7759bed1663)

前面提到聚合函数（count），where 字句无法与聚合函数一起使用。因为 where 子句的运行顺序排在第二，运行到 where 时，表还没有被分组。（如果不清楚，可以系统看下我之前的课程《从零学会 SQL：汇总分析》）

![](https://4109408004-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MTuZ3PxkXf2a7UbRybW%2F-MUhz9BmmT7AltkgZWYm%2F-MUhzs0Q9wv0bS9gps_-%2F%E7%AE%80%E5%8D%95%E6%9F%A5%E8%AF%A2_8.jpg?alt=media\&token=278961f1-b0e8-421f-a1cf-76e6a6f8a901)

如果要对分组查询的结果进行筛选，可以使用 having 子句。所以，这道题的最优方法如下：

```sql
select 姓名
from 学生表
group by 姓名
having count(姓名) > 1;
```

**【本题考点】**

1）考察思路，有两种解题方法，但是使用 having 语句的方法更高效。

2）考察对 having 语句的掌握，很多人会把聚合函数写到 where 子句中。

3）熟记 SQL 子句的书写顺序和运行顺序。

**【举一反三】**

本题也可以拓展为：找出重复出现 n 次的数据。只需要改变 having 语句中的条件即可：

```sql
select 列名
from 表名
group by 列名
having count(列名) > n;
```

推荐：[如何提升你的分析技能，实现升职加薪？](http://mp.weixin.qq.com/s?__biz=MzAxMTMwNTMxMQ==\&mid=2649246542\&idx=2\&sn=522f75638ff0e49fb23c1c74b89e3db9\&chksm=835fc37eb4284a68e2f1d31d53323e37f36f2637070aaf594edabbb376a0416d09315b9d0bee\&scene=21#wechat_redirect)

![](https://4109408004-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MTuZ3PxkXf2a7UbRybW%2F-MUhz9BmmT7AltkgZWYm%2F-MUhzuyNcbCCJOnfrBgJ%2F%E7%AE%80%E5%8D%95%E6%9F%A5%E8%AF%A2_9.jpg?alt=media\&token=8fbbd8d3-a04e-4f3f-b54e-243cea601755)
