여러 SQL 문제를 풀던 중 같은 개체가 여러 시점(year)에 등장하는 데이터를 다루다가 몇가지 실수가 있어서 정리한다.
participation (
athlete_id INT,
year INT,
team_code VARCHAR,
sport VARCHAR
)
athlete_info (
id INT,
name VARCHAR
)
목표 : 같은 개체가 4년 간격으로 연속 등장한 기록을 찾는 것.
LAG(year) OVER (PARTITION BY athlete_id ORDER BY athlete_id)
PARTITION 내부에서는 athlete_id가 전부 동일하므로
ORDER BY athlete_id는 사실상 의미가 없다.
결국 LAG는 “들어온 순서” 기준으로 계산된다.
데이터가 우연히 연도순으로 들어온 경우에는 맞게 보이지만,
순서가 조금만 뒤섞이면 결과가 바로 틀어진다.
LAG(p.year) OVER (
PARTITION BY p.athlete_id
ORDER BY p.year
)
- PARTITION BY 는 그룹을 나누는 기준
- ORDER BY 는 그룹 내부에서 비교 순서를 결정하는 기준
JOIN이 여러 개일 때 CTE 내부에서 SELECT *를 사용하면
id 컬럼이 여러 테이블에서 중복되어 오류가 발생한다.
특히 CTE는 “하나의 테이블”처럼 취급되므로
컬럼명 충돌에 매우 민감하다.
그래서 필요한 컬럼만 명시적으로 적는 방식으로 바꿨다.
WITH sorted AS (
SELECT
a.id AS athlete_id,
a.name,
p.year,
LAG(p.year) OVER (
PARTITION BY a.id
ORDER BY p.year
) AS prev_year
FROM participation p
JOIN athlete_info a ON p.athlete_id = a.id
WHERE p.sport = '여자 배구'
AND p.team_code = 'KOR'
)
SELECT DISTINCT
athlete_id AS id,
name
FROM sorted
WHERE year - prev_year = 4;
이 쿼리의 핵심 로직:
- 같은 개체 기준으로 PARTITION
- 시점(year) 기준으로 정렬
- LAG로 이전 연도 계산
year - prev_year = 4조건으로 연속성 판별- DISTINCT로 최종 중복 제거
SELECT *는 컬럼 충돌을 만들기 쉽다.운이 좋아서 해결되는 일이 없도록 예외상황, 변수 등을 다양하게 고려하고 생각해보자!