📝 601. Human Traffic of Stadium
🔹 경기장의 인적 트래픽
연속된 ID를 가진 세 개 이상의 행이 있고, 각 행의 인원이 100명 이상인 레코드를 표시하는 솔루션을 작성하세요. visit_date를 기준으로 오름차순으로 정렬된 결과 테이블을 반환하세요.
📝 문제 설명
조건은 다음과 같습니다:
- people이 100명 이상인 행만 고려
- ID 기준으로 연속된 3개 이상의 행을 추출
- 결과는 visit_date 기준 오름차순 정렬
📊 테이블 구조
Stadium 테이블
Column Name | Type |
id | int |
visit_date | date |
people | int |
💡 SQL 문제 해결 방법
이 문제는 연속된 행을 찾아내야 하므로, 일반적인 GROUP BY로는 해결이 어렵습니다.
윈도우 함수와 누적 그룹핑 기법을 활용하는 것이 핵심입니다.
- 먼저, people >= 100 조건을 만족하는 행만 필터링
- LAG() 함수를 이용해 이전 행의 ID와 비교 → 연속 여부 판단
- 연속되지 않은 지점에서 새로운 그룹을 시작하는 방식으로 그룹핑
- 각 그룹별로 COUNT(id) ≥ 3인 그룹만 추출
- 해당 그룹에 속하는 모든 행을 결과로 반환
🖥️ SQL 풀이
SELECT id
, visit_date
, people
FROM (
SELECT *
, COUNT(id) OVER (PARTITION BY grp) AS ysno_code
FROM (
SELECT *
, SUM(continuity) OVER (ORDER BY id) AS grp
FROM (
SELECT *
, CASE WHEN id = LAG(id) OVER (ORDER BY id) + 1 THEN 0 ELSE 1 END AS continuity
FROM Stadium
WHERE people >= 100
) sub1
) sub2
) sub3
WHERE ysno_code >= 3
ORDER BY visit_date;
🔍 쿼리 분석
- WHERE people >= 100: 100명 이상 조건 먼저 필터링
- LAG(id) + CASE WHEN: 이전 행과의 id 차이를 비교해 연속 여부 판단
- SUM(continuity) OVER (...): 연속된 구간마다 고유 그룹 번호 부여
- COUNT(id) OVER (PARTITION BY grp): 각 그룹의 행 개수 계산
- WHERE ysno_code >= 3: 3개 이상 연속된 그룹만 필터링
📌 실행 예제
📊 입력 데이터
Stadium 테이블
id | visit_date | people |
1 | 2017-01-01 | 10 |
2 | 2017-01-02 | 109 |
3 | 2017-01-03 | 150 |
4 | 2017-01-04 | 99 |
5 | 2017-01-05 | 145 |
6 | 2017-01-06 | 1455 |
7 | 2017-01-07 | 199 |
8 | 2017-01-09 | 188 |
쿼리 실행 결과
id | visit_date | people |
5 | 2017-01-05 | 145 |
6 | 2017-01-06 | 1455 |
7 | 2017-01-07 | 199 |
8 | 2017-01-09 | 188 |
📌 보충설명
✅ Step 1: WHERE people >= 100
id | visit_date | people |
2 | 2017-01-02 | 109 |
3 | 2017-01-03 | 150 |
5 | 2017-01-05 | 145 |
6 | 2017-01-06 | 1455 |
7 | 2017-01-07 | 199 |
8 | 2017-01-09 | 188 |
✅ Step 2: LAG(id) + CASE WHEN → continuity 계산
- id가 연속되는지 확인해서 연속이면 0, 끊기면 1
id | visit_date | people | lag(id) | continuity |
2 | 2017-01-02 | 109 | null | 1 |
3 | 2017-01-03 | 150 | 2 | 0 |
5 | 2017-01-05 | 145 | 3 | 1 |
6 | 2017-01-06 | 1455 | 5 | 0 |
7 | 2017-01-07 | 199 | 6 | 0 |
8 | 2017-01-09 | 188 | 7 | 0 |
- 연속되는 구간: 2-3, 5-6-7-8
- id 4는 제외된 상태 (people < 100)
✅ Step 3: SUM(continuity) OVER (ORDER BY id) → 그룹핑
- continuity = 1일 때 새로운 그룹 시작. SUM() 누적으로 그룹 번호 생성.
id | visit_date | people | continuity | grp |
2 | 2017-01-02 | 109 | 1 | 1 |
3 | 2017-01-03 | 150 | 0 | 1 |
5 | 2017-01-05 | 145 | 1 | 2 |
6 | 2017-01-06 | 1455 | 0 | 2 |
7 | 2017-01-07 | 199 | 0 | 2 |
8 | 2017-01-09 | 188 | 0 | 2 |
- 그룹 1: 2-3
- 그룹 2: 5-6-7-8
✅ Step 4: COUNT(id) OVER (PARTITION BY grp) → 그룹 내 행 개수
id | visit_date | people | grp | ysno_code |
2 | 2017-01-02 | 109 | 1 | 2 |
3 | 2017-01-03 | 150 | 1 | 2 |
5 | 2017-01-05 | 145 | 2 | 4 |
6 | 2017-01-06 | 1455 | 2 | 4 |
7 | 2017-01-07 | 199 | 2 | 4 |
8 | 2017-01-09 | 188 | 2 | 4 |
✅ Step 5: WHERE ysno_code >= 3 → 3개 이상인 그룹만 필터링
id | visit_date | people |
5 | 2017-01-05 | 145 |
6 | 2017-01-06 | 1455 |
7 | 2017-01-07 | 199 |
8 | 2017-01-09 | 188 |
🎯 결론
이 문제는 LAG(), SUM() OVER, COUNT() OVER 같은 윈도우 함수를 복합적으로 활용하는 고급 SQL 문제입니다.
특히 연속된 조건을 만족하는 그룹핑 로직은,
👉 출석 연속일 계산, 구매 패턴 분석, 이탈 시점 분석 등 다양한 실무에도 응용될 수 있어요!
윈도우 함수와 누적 그룹핑 로직을 익혀두면, 데이터 분석 능력도 한층 더 올라갑니다 😊
더 많은 SQL 문제 풀이를 보고 싶다면 LeetCode SQL 문제 모음을 확인해 보세요! 🚀
728x90
반응형
'LeetCode' 카테고리의 다른 글
[LeetCode] 262. Trips and Users (2) | 2025.04.18 |
---|---|
[LeetCode] 1393. Capital Gain/Loss (0) | 2025.04.17 |
[LeetCode] 1158. Market Analysis 1 (0) | 2025.04.16 |
[LeetCode] 608. Tree Node (0) | 2025.04.16 |
[LeetCode] 184. Department Highest Salary (0) | 2025.03.26 |