SQL로 데이터를 분석하다 보면 단순한 GROUP BY나 JOIN만으로는 부족할 때가 많습니다.
예를 들어:
- 사용자별 순위를 매기고 싶을 때
- 하루하루의 누적합을 구하고 싶을 때
- 전년 대비 매출 변화율을 보고 싶을 때
이럴 때 사용하는 강력한 도구가 바로 윈도우 함수(Window Function) 입니다. 이번 글에서는 자주 사용되는 대표 윈도우 함수인 ROW_NUMBER, RANK, LAG, LEAD, OVER(PARTITION BY)를 설명하고, 실무 예제를 통해 어디에 어떻게 활용할 수 있는지 살펴보겠습니다.
윈도우 함수란?
윈도우 함수(Window Function)는 여러 행을 기준으로 계산하면서도 각 행의 값을 유지하는 함수입니다. 즉, 일반적인 집계 함수(SUM, AVG 등)는 그룹을 하나로 모으지만, 윈도우 함수는 모든 행을 유지하면서도 계산을 수행합니다.
기본 구조:
함수명() OVER (
PARTITION BY 그룹컬럼
ORDER BY 정렬컬럼
)
ROW_NUMBER() – 고유한 순번 매기기
ROW_NUMBER()는 지정한 그룹 안에서 고유한 일련 번호를 부여합니다.
예제: 부서별로 급여 순위 매기기
SELECT name, department, salary,
ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) AS rank
FROM employees;
PARTITION BY는 그룹 기준, ORDER BY는 순번 정렬 기준입니다.
💡 동일한 급여를 가진 사람도 각각 다른 순번이 부여됩니다 (무조건 1, 2, 3...으로).
RANK() / DENSE_RANK() – 순위 부여
🔸 RANK()
같은 값에 같은 순위를 부여
다음 순위는 건너뜀
🔸 DENSE_RANK()
같은 값에 같은 순위를 부여
다음 순위는 바로 다음
예제:
SELECT name, salary,
RANK() OVER (ORDER BY salary DESC) AS rank,
DENSE_RANK() OVER (ORDER BY salary DESC) AS dense_rank
FROM employees;
이름 급여 RANK DENSE_RANK
A | 5000 | 1 | 1 |
B | 5000 | 1 | 1 |
C | 4500 | 3 | 2 |
🟡 RANK는 2번 건너뛰고 3위로 넘어갑니다.
LAG() / LEAD() – 이전/다음 행 비교하기
LAG(col) : 바로 이전 행의 값
LEAD(col) : 바로 다음 행의 값
예제: 전월 대비 매출 비교
SELECT month, sales,
LAG(sales) OVER (ORDER BY month) AS prev_sales,
sales - LAG(sales) OVER (ORDER BY month) AS sales_diff
FROM monthly_sales;
월 매출 전월 매출 매출 증감
Jan | 1000 | NULL | NULL |
Feb | 1200 | 1000 | 200 |
Mar | 900 | 1200 | -300 |
📌 LAG는 기준 행 이전의 값을 참조, LEAD는 다음 행의 값을 참조합니다.
누적합(Cumulative Sum) 구하기 – SUM() OVER
누적합은 일별, 월별 데이터를 누적해서 보는 데 자주 사용됩니다.
예제: 일별 판매량 누적합
SELECT sale_date, product, quantity,
SUM(quantity) OVER (PARTITION BY product ORDER BY sale_date) AS running_total
FROM sales;
날짜 상품 판매량 누적 판매량
1/1 | A | 10 | 10 |
1/2 | A | 5 | 15 |
1/3 | A | 8 | 23 |
전년 대비 증감률 계산 (YoY Change)
윈도우 함수를 사용하면 전년도 값을 참조해 손쉽게 변화율 계산이 가능합니다.
예제: 연도별 매출 변화율
SELECT year, revenue,
LAG(revenue) OVER (ORDER BY year) AS prev_year,
ROUND(((revenue - LAG(revenue) OVER (ORDER BY year)) / LAG(revenue) OVER (ORDER BY year)) * 100, 2) AS growth_rate
FROM annual_sales;
연도 매출 전년도 성장률 (%)
2021 | 1000 | NULL | NULL |
2022 | 1100 | 1000 | 10.00 |
2023 | 900 | 1100 | -18.18 |
정리: 자주 쓰는 윈도우 함수 요약표
함수 설명 사용 예시
ROW_NUMBER() | 고유 일련번호 | 부서별 1등 직원 뽑기 |
RANK() | 중복 순위, 건너뛰는 랭킹 | 대회 점수 순위 매기기 |
DENSE_RANK() | 중복 순위, 건너뛰지 않음 | 상품 가격 순위 |
LAG() | 이전 행 참조 | 전월 대비 매출 비교 |
LEAD() | 다음 행 참조 | 다음 이벤트 예측 |
SUM() OVER | 누적합, 그룹 내 합계 | 월별 누적 판매량 |
💡 윈도우 함수는 언제 쓰면 좋을까?
1. 순위나 랭킹이 필요할 때
2. 이전 또는 다음 값과 비교할 때
3. 누적합, 누적 평균이 필요할 때
4. GROUP BY 없이도 행을 유지하면서 집계해야 할 때
🧠 마무리하며
윈도우 함수는 SQL에서 단순한 집계를 넘어서 행간 연산, 비교, 누적 계산, 순위 매기기 등 복잡한 데이터 분석 작업을 훨씬 쉽게 만들어줍니다. 특히 BI 도구, 리포트, 대시보드 구현 시 윈도우 함수는 필수적인 도구로 활용됩니다. 처음엔 생소할 수 있지만, 실무에 적용해보며 익숙해지면 SQL의 강력한 분석 도구가 되어줄 거예요!