본문 바로가기
SQL

Window Function (윈도우 함수) - MySQL

by 바른곰의 SQL천국 2025. 7. 29.

Window Function (윈도우 함수) - 집계 결과를 여러 행에 걸쳐 출력

 

- 왜 사용하는 가?

  • GROUP BY 와 달리 모든 행을 유지하면서 행 단위로 누적합, 순위, 이전값 등 계산 가능
  • 즉, 모든 행과 집계정보를 함께 보고 싶을 때 사용

 

- Window Function 의 종류

 

- 구조

<윈도우 함수>() OVER ( # 윈도우 함수임을 나타내는 키워드
  [PARTION BY <컬럼>] # 데이터를 그룹으로 나눔
  [ORDER BY <컬럼>] # 순서 기준을 지정
)

 

- 예시

 

1. ROW_NUMBER( ) : 순위를 1부터 부여 (중복 시에도 무조건 증가) (동점이 있어도 1, 2, 3, 4)

-- 각 유저별 최근 1건 주문 추출
SELECT
	user_id,
    order_date,
    amount,
    ROW_NUMBER() OVER (PARTITION BY user_id, ORDER BY order_date) AS row_num
FROM orders

 

 

2. RANK( ) : 동점 순위 부여하고 다음 순위는 건너뜀 (1, 1, 3, 4)

-- 유저별로 주문 금액의 순위를 계산 (단, 다음 순위 건너뜀)
SELECT
	user_id,
    amount,
    RANK() OVER (PARTITION BY user_id, ORDER BY amount DESC) AS rank_amount
FROM orders

 

 

3. DENSE_RANK( ) : 동점 순위 부여하되 다음 순위는 건너뛰지 않음 (1, 1, 2, 3)

-- 유저별로 주문 금액의 순위를 계산 (단, 다음 순위 건너뛰지 않음)
SELECT
	user_id,
    amount,
    DENSE_RANK() OVER (PARTITION BY

 

 

4. SUM( ) / AVG( ) : 누적합 계산 / 누적 평균 계산

-- 유저별 누적 구매액 계산
-- 유저별 누적 평균 구매액 계산
SELECT
	user_id,
    order_date,
    SUM(amount) OVER (PARTITION BY user_id ORDER BY order_date) AS cumulative_sum,
    AVG(amount) OVER (PARTITION BY user_id ORDER BY order_date) AS cumulative_avg
FROM orders

 

 

5. LAG( ) / LEAD( ) : 이전값 / 다음값 참조

-- 유저와 이전유저, 다음유저의 결제 금액을 출력
SELECT
	user_id,
    order_date,
    amount,
    LAG(amount) OVER (PARTITION BY user_id ORDER BY order_date) AS prev_amount,
    LEAD(amount) OVER (PARTITION BY user_id ORDER BY order_date) AS next_amount
FROM orders

 

예시 테이블 :

user_id order_date amount
A 2024-01-01 100
A 2024-01-03 300
A 2024-01-05 200

 

출력 결과 : 

user_id order_date amont prev_amount next_amount
A 2024-01-01 100 NULL 300
A 2024-01-03 300 100 200
A 2024-01-05 200 300 NULL

 

 

6. NTILE(n) : n등분한 후 각 행이 소속해 있는 그룹 부여

-- 상위 50%, 하위 50% 구분

SELECT
	user_id,
    amount,
    NTILE(2) OVER (ORDER BY amount DESC) AS quartile # 전체를 2등분
FROM orders

 

 

7. FIRST_VALUE( ) : 그룹 내 첫번째 값

-- 유저별 첫 주문금액
SELECT
	user_id,
    order_date,
    amount,
    FIRST_VALUE(amount) OVER (PARTITION BY user_id ORDER BY order_date) AS first_order
FROM orders

 

 

8. LAST_VALUE( ) : 그룹 내 마지막번째 값

-- 유저별 마지막 주문 금액
SELECT
	user_id,
    order_date,
    amount,
    LAST_VALUE(amount) OVER 
    	(PARTITION BY user_id 
        ORDER BY order_date
        ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS last_amount
FROM orders

 

ROWS BETWEEN으로 범위를 지정해줘야한다고 한다. 그렇지 않으면 현재 행 기준에서 가장 마지막 값이 출력되기 때문라는데... 아직은 잘 모르겠다. ROWS, RANGE는 다음 글에서 제대로 공부해야 겠다.

 

 

9. COUNT( ) : 누적 갯수 계산

-- 유저별 누적 주문 횟수
SELECT
	user_id,
    order_date,
    COUNT(*) OVER (PARTITION BY user_id ORDER BY order_date_ AS order_count
FROM orders

'SQL' 카테고리의 다른 글

Common Table Expression (CTE) - MySQL  (4) 2025.08.03
ROWS & RANGE (feat. Window Function) - MySQL  (5) 2025.08.01
Subquery (서브쿼리) - MySQL  (1) 2025.07.27
집계 함수 & GROUP BY & HAVING - MySQL  (2) 2025.07.25
JOIN (조인) - MySQL  (1) 2025.07.23