윈도우 함수란?
아래와 같은 주문 데이터 셋이 있다고 가정해보자
Date | Customer | Order_ID | Amount |
2025-05-01 | Alice | 101 | 5 |
2025-05-02 | Alice | 102 | 7 |
2025-05-03 | Alice | 103 | 10 |
2025-05-04 | Bob | 104 | 4 |
2025-05-05 | Bob | 105 | 6 |
우리는 이 데이터 셋에서 5월 1일부터 5월 5일까지 어떤 고객이 어떤 주문 ID를 통해 얼마나 주문했는지 알 수 있다.
하지만 이것은 원시 데이터이고 아주 간단하면서도 적은 양이기 때문에 실제로 엄청나게 많은 양의 데이터를 한눈에 보는 것은 어렵다. 해서 조금 더 한눈에 볼 수 있고 의미있는 데이터를 보기 위해서는 각 고객별로 얼마나 주문을 했는지의 집계를 보고 싶을 수 있다.
집계를 내고 보는 방법은 다양하다.
오늘은 윈도우 함수라는 것을 사용해서 통계를 볼 것이다.
윈도우 함수란 무엇인가?
윈도우 함수는 행들의 집합(윈도우)에 대해 계산을 수행하는 함수이다. 기존의 GROUP BY와 달리, 윈도우 함수는 원본 데이터의 개별 행을 그대로 유지하면서 집계 결과를 각 행에 추가할 수 있다. 즉, 데이터를 축소하지 않고 분석 정보를 추가할 수 있는 강력한 도구인 셈이다.
윈도우 함수의 주요 특징은 아래와 같다.
1. 원본 데이터의 행을 유지하면서 집계 결과를 표시
2. 행과 행 사이의 관계를 분석 가능
3. 누적 집계, 순위 매기기, 이동 평균 등 다양한 분석 가능
그렇다면 왜 윈도우(Window) 인가?
데이터를 바라보는 '창(Window)'이 데이터셋을 따라 이동하면서 특정 그룹의 데이터를 분석하기 때문이다. 마치 창문을 통해 밖을 바라보듯, 윈도우 함수는 지정된 범위의 데이터만을 대상으로 계산을 수행한다. 이 창은 고정될 수도 있고, 현재 행을 기준으로 이동할 수도 있어. 이걸 통해 누적 합계, 이동 평균 등 다양한 분석이 가능해진다.
위 그림을 보면 일련의 데이터가 있고 이걸 보는 Window (창)이 옆으로 슬라이딩 되는 것을 볼 수 있다.
윈도우 함수를 통해 합(SUM), 누계(Running Total), 평균(AVG), 순위(RANK), 이전 데이터(LAG), 이후 데이터(LEAD), 순번 (Row num) 등을 알아낼 수 있다.
예시 1번:
Date | Customer | Order ID | Amount | SUM | Running Total | AVG | RANK |
2025-05-01 | Alice | 101 | 5 | 32 | 5 | 5 | 4 |
2025-05-02 | Alice | 102 | 7 | 32 | 12 | 6 | 2 |
2025-05-03 | Alice | 103 | 10 | 32 | 22 | 7.333333 | 1 |
2025-05-04 | Bob | 104 | 4 | 32 | 26 | 6.5 | 5 |
2025-05-05 | Bob | 105 | 6 | 32 | 32 | 6.4 | 3 |
이런식으로 원본 데이터 셋을 건드리지 않고 신규 칼럼을 옆에 두면서 그 행의 특정 데이터, 여기서는 전체 데이터 셋을 하나의 창으로 보고 어떠한 그룹핑이나 분류 없이 Amount(주문 건수)를 행마다 통계한것이다. 하지만 아직 부족하다. 이는 전체 데이터 셋을 하나의 창으로 본 것이고 고객별로 그룹된 집계는 아니다. 윈도우 함수가 강력하고 효율적인 이유는 바로 이 그룹핑에 있다. 고객별로 그룹핑을 한다면 위 테이블은 아래와 같이 나올 것이다.
예시 2번:
Date | Customer | Order_ID | Amount | SUM | Running Total | AVG | RANK |
2025-05-01 | Alice | 101 | 5 | 22 | 5 | 7.3333 | 3 |
2025-05-02 | Alice | 102 | 7 | 22 | 12 | 7.3333 | 2 |
2025-05-03 | Alice | 103 | 10 | 22 | 22 | 7.3333 | 1 |
2025-05-04 | Bob | 104 | 4 | 10 | 4 | 5 | 2 |
2025-05-05 | Bob | 105 | 6 | 10 | 10 | 5 | 1 |
문법:
SELECT
Date,
Customer,
Order_ID,
Amount,
SUM(Amount) OVER (PARTITION BY Customer) AS SUM,
SUM(Amount) OVER (PARTITION BY Customer ORDER BY Date) AS RUNNING_TOTAL,
AVG(Amount) OVER (PARTITION BY Customer) AS AVG,
RANK() OVER (PARTITION BY Customer ORDER BY Amount DESC) AS RANK,
FROM Orders
ORDER BY Customer, Date;