180. 连续出现的数字

表:Logs

1
2
3
4
5
6
7
8
+-------------+---------+
| Column Name | Type |
+-------------+---------+
| id | int |
| num | varchar |
+-------------+---------+
在 SQL 中,id 是该表的主键。
id 是一个自增列。

找出所有至少连续出现三次的数字。

返回的结果表中的数据可以按 任意顺序 排列。

结果格式如下面的例子所示:

示例 1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
输入:
Logs 表:
+----+-----+
| id | num |
+----+-----+
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 2 |
| 5 | 1 |
| 6 | 2 |
| 7 | 2 |
+----+-----+
输出:
Result 表:
+-----------------+
| ConsecutiveNums |
+-----------------+
| 1 |
+-----------------+
解释:1 是唯一连续出现至少三次的数字。

解题思路

核心思路是 “通过自连接匹配连续三行的数字”
由于 id 是自增列,连续出现的数字对应的 id 必然是连续的(如 id=1,2,3 对应连续三行)。通过将 Logs 表与自身进行两次连接,分别匹配 “当前行与下一行”“当前行与下下一行”,筛选出三行 num 完全相同的记录,最后去重得到结果。

具体步骤:

  1. 三次表连接:将 Logs 表分别作为 l1(当前行)、l2(下一行,id=l1.id+1)、l3(下下一行,id=l1.id+2);
  2. 筛选连续相同数字:添加条件 l1.num = l2.num AND l2.num = l3.num,确保三行数字完全一致;
  3. 去重:使用 DISTINCT 避免同一数字因多次连续出现(如连续 4 次)而重复输出。

代码实现

1
2
3
4
5
6
7
8
9
10
SELECT DISTINCT
l1.num AS ConsecutiveNums
FROM
Logs l1
JOIN
Logs l2 ON l1.id = l2.id - 1 -- l2是l1的下一行(id差1)
JOIN
Logs l3 ON l1.id = l3.id - 2 -- l3是l1的下下一行(id差2)
WHERE
l1.num = l2.num AND l2.num = l3.num; -- 三行数字完全相同