180. Consecutive Numbers; LEAD, SELF JOIN
https://leetcode.com/problems/consecutive-numbers/submissions/1908605113/
1. Problem
Logs 테이블에서 최소 3번 연속으로 등장하는 모든 숫자를 찾아야 한다.
- 핵심 과제: 행과 행 사이의 관계를 파악하여, 현재 행과 다음 행, 그리고 그다음 행의 값이 모두 일치하는지 검증하는 것이다.
2. Solution: 두 가지 정석 접근법
① LEAD() 윈도우 함수 활용 (현대적 방식) 현재 행을 기준으로 미래의 행(1번째 뒤, 2번째 뒤)을 미리 끌어와서 한 줄에서 비교한다.
② 삼중 Self Join 활용 (전통적 방식) 테이블을 세 번 불러와서(l1, l2, l3), ID가 1씩 차이 나는 행들끼리 결합한다.
3. Takeaway: 왜 이 풀이들이 객관적으로 우수한가? (객관적 분석)
- LEAD()의 효율성: 서브쿼리 한 번으로 '미래의 데이터'를 현재 행 옆으로 붙여주기 때문에 가독성이 뛰어나며, 연속 조건이 4회, 5회로 늘어나도 LEAD 함수 줄만 추가하면 되어 확장이 간편하다.
- Self Join의 논리: 유진 님이 그려주신 조인 결과 표를 보면 알 수 있듯이, id를 기준으로 데이터를 수평으로 길게 늘어뜨려 비교하는 직관적인 집합론적 접근이다. 인덱스(id)가 잘 잡혀 있다면 성능 면에서도 나쁘지 않은 선택이다.
- DISTINCT의 필수성: 한 숫자가 4번 이상 연속될 경우(예: 1, 1, 1, 1), 1번-2번-3번 조합과 2번-3번-4번 조합 모두 조건을 만족하게 된다. 중복 결과를 방지하기 위해 DISTINCT를 사용하는 것이 무결성의 핵심이다.
Table: Logs
+-------------+---------+
| Column Name | Type |
+-------------+---------+
| id | int |
| num | varchar |
+-------------+---------+
In SQL, id is the primary key for this table.
id is an autoincrement column starting from 1.
Find all numbers that appear at least three times consecutively.
Return the result table in any order.
The result format is in the following example.
Example 1:
Input:
Logs table:
+----+-----+
| id | num |
+----+-----+
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 2 |
| 5 | 1 |
| 6 | 2 |
| 7 | 2 |
+----+-----+
Output:
+-----------------+
| ConsecutiveNums |
+-----------------+
| 1 |
+-----------------+
Explanation: 1 is the only number that appears consecutively for at least three times.
1. LEAD 분석함수
LEAD() 함수는 파티션별 윈도우에서 지정한 이후 행의 값을 가져온다.
- 3개의 인자 사용:
LEAD(가져올 값, 이후 몇번째 행, 가져올 데이터가 없을 때 값) OVER (PARTIITION BY 구간 나눌 열, ORDER BY 정렬할 열) LEAD로 생성할 열 이름
- WINDOWING 절을 사용할 수 없다.
# MySQL 8.0ver 이상에서만 윈도우 함수(LEAD, LAG, OVER)를 지원
SELECT DISTINCT num as ConsecutiveNums
FROM (
SELECT num,
LEAD(num,1) OVER (ORDER BY id) as next_num
LEAD(num,2) OVER (ORDER BY id) as next_next_num
FROM Logs
) AS t
WHERE num = next_num AND num = next_next_num;
2. 삼중 Self Join으로 풀이
역방향(+1, +2)이 아닌 순방향 조인(-1, -2)을 사용
# Self Join
SELECT DISTINCT l1.num as ConsecutiveNums
FROM Logs l1
JOIN Logs l2 on l1.id = l2.id -1 # +1 이 아니고 -1
JOIN Logs l3 on l1.id = l3.id -2 # +2 이 아니고 -2
WHERE l1.num = l2.num AND l1.num = l3.num;
| l1 | l2 | l3 | |||
| id | num | id | num | id | num |
| 1 | 1 | 2 | 1 | 3 | 1 |
| 2 | 1 | 3 | 1 | 4 | 2 |
| 3 | 1 | 4 | 2 | 5 | 1 |
| 4 | 2 | 5 | 1 | 6 | 2 |
| 5 | 1 | 6 | 2 | ||
| 6 | 2 |
'Data Science > SQL' 카테고리의 다른 글
| T사 SQL 쿼리테스트 대비3: 퍼널 분석 (Funnel Analysis) (0) | 2026.02.05 |
|---|---|
| T사 SQL 쿼리테스트 대비2: A/B테스트 (0) | 2026.02.05 |
| T사 SQL 쿼리테스트 대비: MAU (0) | 2026.02.05 |
| [SQL/함수] N번째 높은 급여 찾기: 사용자 정의 함수 CREATE FUNCTION와 OFFSET (LeetCode177 Medium) (1) | 2026.02.04 |
| C사 Business Analyst SQL 쿼리테스트 학습 목표 (0) | 2026.02.04 |