Programming

SQL 고급: 윈도우 함수(Window Functions) & 서브쿼리(Subquery) 완전 정복

Lucas.Kim 2025. 12. 8. 11:27
반응형

SQL 중급까지 학습했다면 이제 본격적인 데이터 분석 단계에서 자주 사용되는 윈도우 함수(Window Functions)서브쿼리(Subquery) 를 학습해야 합니다.
윈도우 함수는 기존 GROUP BY로는 표현하기 어려운 누적값, 순위, 이동평균, 비율 계산 등을 매우 쉽게 만들 수 있는 고급 SQL 기능입니다.
서브쿼리는 쿼리 안에서 또 다른 쿼리를 실행하여 결과를 비교, 필터링, 집계할 때 활용합니다.

둘 다 실무 분석에서 매우 많이 등장하는 고급 SQL 기능으로, 이 글에서는 핵심 개념과 예제를 중심으로 설명합니다.

1. 윈도우 함수(Window Functions) 기본 개념

윈도우 함수는 다음과 같은 패턴으로 사용됩니다.

function() OVER (
    PARTITION BY column
    ORDER BY column
    ROWS BETWEEN ...
)

주요 기능

  • 누적합(Cumulative Sum)
  • 순위(RANK, DENSE_RANK, ROW_NUMBER)
  • 이전 값/다음 값 (LAG, LEAD)
  • 이동평균(Moving Average)
  • 전체 대비 비율 계산

GROUP BY와 달리 데이터가 집약되지 않고 원본 행이 그대로 유지되는 것이 핵심 차이점입니다.

2. 윈도우 함수 예제

2-1. 행 번호 붙이기: ROW_NUMBER()

SELECT 
    title,
    release_year,
    ROW_NUMBER() OVER (ORDER BY release_year) AS row_num
FROM films;

결과 예시:

Film A 1980 1
Film B 1981 2

 

2-2. 순위 매기기: RANK(), DENSE_RANK()

SELECT 
    title,
    gross,
    RANK() OVER (ORDER BY gross DESC) AS gross_rank
FROM films;

 

  • RANK() : 동점 순위 발생 시 건너뛰기
  • DENSE_RANK() : 순위 건너뛰지 않음

2-3. 누적합(Cumulative Sum)

SELECT 
    release_year,
    gross,
    SUM(gross) OVER (ORDER BY release_year) AS cumulative_gross
FROM films;

 

결과 예시:

1990 500000 500000
1991 700000 1,200,000
1992 800000 2,000,000

 

2-4. PARTITION BY 사용: 연도별 순위 구하기

SELECT 
    title,
    release_year,
    gross,
    RANK() OVER (PARTITION BY release_year ORDER BY gross DESC) AS rank_in_year
FROM films;

→ 같은 연도끼리 묶어서 순위를 매깁니다.

 

2-5. 이전 행과 비교: LAG()

SELECT
    release_year,
    gross,
    LAG(gross, 1) OVER (ORDER BY release_year) AS previous_year_gross
FROM films;

이전의 gross 값을 함께 확인할 수 있습니다.

 

2-6. 이동 평균(Moving Average)

SELECT
    release_year,
    gross,
    AVG(gross) OVER (
        ORDER BY release_year
        ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
    ) AS moving_avg_3
FROM films;

→ 최근 3개 영화의 평균 계산

 

3. 서브쿼리(Subquery) 기본 개념

서브쿼리는 SQL 문 안에 포함된 다른 쿼리를 의미합니다. 활용 방식은 크게 세 가지입니다.

1) SELECT 절에서 사용 (스칼라 서브쿼리)

2) FROM 절에서 사용 (파생 테이블)

3) WHERE 절에서 사용 (조건 필터링)

4. 서브쿼리 예제

4-1. WHERE 절에서: 특정 조건을 가진 행만 조회

예: 전체 평균보다 높은 gross를 가진 영화만 조회

SELECT title, gross
FROM films
WHERE gross > (
    SELECT AVG(gross)
    FROM films
);

4-2. IN 서브쿼리: 특정 감독의 영화만 조회

SELECT title, director
FROM films
WHERE director IN (
    SELECT name
    FROM people
    WHERE role = 'Director'
);

 

4-3. NOT IN 서브쿼리: 데이터 제외

SELECT title
FROM films
WHERE title NOT IN (
    SELECT title
    FROM banned_films
);

4-4. FROM 절 서브쿼리: 파생 테이블 사용

연도별 평균 gross를 계산한 뒤 다시 필터링할 때 사용합니다.

SELECT *
FROM (
    SELECT 
        release_year,
        AVG(gross) AS avg_gross
    FROM films
    GROUP BY release_year
) AS yearly_stats
WHERE avg_gross > 100000000;

4-5. SELECT 절 서브쿼리: 한 행에 요약치 포함

SELECT 
    title,
    gross,
    (SELECT AVG(gross) FROM films) AS global_avg
FROM films;

모든 행에 전체 평균을 함께 보여 줍니다.

4-6. 윈도우 함수와 서브쿼리 혼합

가장 흔한 실무 패턴 중 하나입니다.

SELECT *
FROM (
    SELECT 
        title,
        release_year,
        gross,
        RANK() OVER (PARTITION BY release_year ORDER BY gross DESC) AS year_rank
    FROM films
) ranked
WHERE year_rank = 1;

→ 연도별 최고 매출 영화만 조회

 

SQL에서 윈도우 함수(Window Functions)서브쿼리(Subquery) 는 데이터 분석 능력을 한 단계 확장시키는 핵심 기능입니다.
윈도우 함수는 “요약하면서도 행을 유지하는” 분석을 가능하게 만들고, 서브쿼리는 복잡한 조건과 비교 연산을 구조적으로 해결합니다.
특히 누적합, 순위, 전년 대비 계산, 이동평균, 파생 테이블, IN/NOT IN 서브쿼리는 기업 데이터 분석에서 매우 자주 등장하므로 반드시 익혀두어야 합니다.

반응형