You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MySQL查找重复行:三个查询结果差异及疑问解析

MySQL重复行查询结果差异解析

表结构

| Field      | Type                            | NULL | Key | Extra          |
| id         | int(11)                         | NO   | PRI | auto_increment |
| name       | varchar(50)                     | YES  |     |                |
| membership | enum('Silver','Gold','Diamond') | YES  |     |                |
| interest   | set('Movie','Music','Concert')  | YES  |     |                |

现有数据

+----+--------+------------+---------------+
| id | name   | membership | interest      |
+----+--------+------------+---------------+
|  1 | Sourav | Silver     | Movie,Concert |
|  2 | Yash   | Diamond    | Music         |
|  3 | Yash   | Diamond    | Music         |
|  4 | Yash   | Diamond    | Music         |
|  5 | Yash   | Diamond    | Music         |
|  6 | Yash   | Diamond    | Music         |
|  7 | Yash   | Diamond    | Music         |
|  8 | Yash   | Diamond    | Music         |
|  9 | Yash   | Diamond    | Music         |
| 10 | Yash   | Diamond    | Music         |
| 11 | Yash   | Diamond    | Music         |
| 12 | Yash   | Diamond    | Music         |
| 13 | Yash   | Diamond    | Music         |
| 14 | Yash   | Diamond    | Music         |
| 15 | Sneha  | Silver     | Concert       |
+----+--------+------------+---------------+
15 rows in set (0.001 sec)

三个查询及结果

查询1:正确筛选重复行

SELECT id, name, membership, interest, count(*)
FROM clients
GROUP BY name, membership, interest
HAVING count(*) > 1;

结果:

+----+------+------------+----------+----------+
| id | name | membership | interest | count(*) |
+----+------+------------+----------+----------+
|  2 | Yash | Diamond    | Music    |       13 |
+----+------+------------+----------+----------+

查询2:无GROUP BY的HAVING查询

SELECT name, membership, interest, count(*)
FROM clients
HAVING count(*) > 1;

结果:

+--------+------------+---------------+----------+
| name   | membership | interest      | count(*) |
+--------+------------+---------------+----------+
| Sourav | Silver     | Movie,Concert |       15 |
+--------+------------+---------------+----------+

查询3:仅GROUP BY的查询

SELECT id, name, membership, interest, count(*)
FROM clients
GROUP BY name, membership, interest; 

结果:

+----+--------+------------+---------------+----------+
| id | name   | membership | interest      | count(*) |
+----+--------+------------+---------------+----------+
| 15 | Sneha  | Silver     | Concert       |        1 |
|  1 | Sourav | Silver     | Movie,Concert |        1 |
|  2 | Yash   | Diamond    | Music         |       13 |
+----+--------+------------+---------------+----------+

疑问解析

1. 三个查询结果差异及HAVING的作用

  • 查询1:GROUP BY name, membership, interest会把这三个字段值完全相同的行归为一组,每组统计行数count(*);HAVING count(*) > 1只保留行数大于1的组(即真正的重复组),所以仅返回Yash的那组数据。
  • 查询2:未写GROUP BY时,MySQL会把整个表当成一个组,count(*)统计全表15行数据,HAVING count(*) >1条件满足,因此返回这个唯一的组;但name, membership, interest会取表中第一行的对应值(Sourav那行),这是MySQL的特殊行为(标准SQL不允许这种写法,因为非聚合字段没有明确分组依据)。
  • 查询3:和查询1一样做了分组,但没有HAVING过滤,所以返回所有分组,不管行数多少,自然结果和前两个查询不同。

HAVING的核心作用是过滤分组后的结果,它和WHERE的区别是:WHERE过滤原始行,HAVING过滤分组后的组,只有配合GROUP BY使用才符合常规业务逻辑(无GROUP BY时仅过滤整个表这个大组)。

2. 第三个查询为何返回唯一条目

GROUP BY name, membership, interest本身会把这三个字段值相同的行合并成一个组,每个组只返回一条结果(组内非聚合字段如id会取组内任意一行的值,这里是组内最早的id),所以看起来像是“去重”后的唯一条目,本质是分组聚合的结果,而非专门的去重操作,但效果类似。

3. Sneha的条目为何排在顶部

MySQL在未指定ORDER BY的情况下,返回结果的顺序是不确定的,取决于存储引擎的物理存储顺序、分组执行计划等。这里Sneha排在前面,只是分组后MySQL返回组的顺序刚好如此,若重新插入数据或优化表,顺序可能改变。如果需要固定顺序,必须显式添加ORDER BY子句。


内容的提问来源于stack exchange,提问作者Yashasvi Haldiya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 09:05:32