MySQL의 윈도우 함수(Window Function) 는 GROUP BY 없이도 행 단위로 집계 연산을 수행
즉, 기존 GROUP BY는 한 행으로 축약되지만, 윈도우 함수는 원본 데이터를 유지하면서 계산 결과를 추가**
윈도우 함수는 OVER() 절과 함께 사용되며, 여러 가지 강력한 기능을 제공 🚀
윈도우_함수(컬럼) OVER (
PARTITION BY 컬럼 -- (선택) 그룹별 연산
ORDER BY 컬럼 -- (선택) 정렬 순서 지정
ROWS BETWEEN ... -- (선택) 특정 범위 지정
)
PARTITION BY → 그룹별 연산 수행 (예: 부서별 평균 급여) ORDER BY → 특정 순서대로 정렬 후 연산 (예: 누적 합계) ROWS BETWEEN → 특정 범위의 행만 계산 (예: 현재 행 ±2개의 행만 평균 계산) | 카테고리 | 함수 | 설명 |
|---|---|---|
| 누적 및 집계 함수 | SUM(), AVG(), COUNT(), MAX(), MIN() | 누적합, 평균, 개수 등 계산 |
| 순위(RANK) 함수 | RANK(), DENSE_RANK(), ROW_NUMBER() | 순위 매기기 |
| 이전/다음 행 참조 | LAG(), LEAD() | 이전 행, 다음 행 값 가져오기 |
| 백분율 함수 | PERCENT_RANK(), CUME_DIST() | 비율(퍼센트) 순위 계산 |
| 순번 함수 | NTILE(n) | 데이터를 n개의 그룹으로 나누기 |
SUM(), AVG(), COUNT(), MAX(), MIN() 등의 집계 함수는 윈도우 함수로 사용 가능해!
SUM())SELECT id, name, salary,
SUM(salary) OVER (ORDER BY id) AS running_total
FROM employees;
✔ ORDER BY id 순서로 salary의 누적 합계를 계산
| id | name | salary | running_total |
|---|---|---|---|
| 1 | Alice | 5000 | 5000 |
| 2 | Bob | 6000 | 11000 |
| 3 | Carol | 7000 | 18000 |
RANK() (동순위 발생)SELECT id, name, salary,
RANK() OVER (ORDER BY salary DESC) AS ranking
FROM employees;
✔ salary 기준으로 순위 매기기 (동점일 경우 순위 건너뜀)
✔ 같은 salary면 같은 순위, 다음 순위는 건너뜀 (1, 2, 2, 4, 5)
| id | name | salary | ranking |
|---|---|---|---|
| 1 | Alice | 7000 | 1 |
| 2 | Bob | 6000 | 2 |
| 3 | Carol | 6000 | 2 |
| 4 | Dave | 5000 | 4 |
DENSE_RANK() (순위 건너뛰지 않음)SELECT id, name, salary,
DENSE_RANK() OVER (ORDER BY salary DESC) AS ranking
FROM employees;
✔ 순위가 연속적으로 유지됨 (1, 2, 2, 3, 4)
| id | name | salary | ranking |
|---|---|---|---|
| 1 | Alice | 7000 | 1 |
| 2 | Bob | 6000 | 2 |
| 3 | Carol | 6000 | 2 |
| 4 | Dave | 5000 | 3 |
ROW_NUMBER() (순위 부여, 중복 없음)SELECT id, name, salary,
ROW_NUMBER() OVER (ORDER BY salary DESC) AS row_num
FROM employees;
✔ 모든 행에 유일한 번호 부여 (동점이라도 순위가 다름)
| id | name | salary | row_num |
|---|---|---|---|
| 1 | Alice | 7000 | 1 |
| 2 | Bob | 6000 | 2 |
| 3 | Carol | 6000 | 3 |
| 4 | Dave | 5000 | 4 |
LAG(), LEAD())LAG() (이전 행 값 가져오기)SELECT id, name, salary,
LAG(salary, 1, 0) OVER (ORDER BY id) AS prev_salary
FROM employees;
✔ 현재 행에서 이전 행의 salary 가져오기 (없으면 0)
| id | name | salary | prev_salary |
|---|---|---|---|
| 1 | Alice | 5000 | 0 |
| 2 | Bob | 6000 | 5000 |
| 3 | Carol | 7000 | 6000 |
LEAD() (다음 행 값 가져오기)SELECT id, name, salary,
LEAD(salary, 1, 0) OVER (ORDER BY id) AS next_salary
FROM employees;
✔ 현재 행에서 다음 행의 salary 가져오기 (없으면 0)
| id | name | salary | next_salary |
|---|---|---|---|
| 1 | Alice | 5000 | 6000 |
| 2 | Bob | 6000 | 7000 |
| 3 | Carol | 7000 | 0 |
PERCENT_RANK() (비율 순위)SELECT id, name, salary,
PERCENT_RANK() OVER (ORDER BY salary DESC) AS percentile_rank
FROM employees;
✔ 전체 데이터에서 현재 값이 몇 % 위치인지 반환 (0 ~ 1 사이 값)
CUME_DIST() (누적 비율)SELECT id, name, salary,
CUME_DIST() OVER (ORDER BY salary DESC) AS cumulative_distribution
FROM employees;
✔ 현재 값까지의 누적 비율(누적 개수 / 전체 개수) 계산
NTILE(n) (그룹 나누기)SELECT id, name, salary,
NTILE(3) OVER (ORDER BY salary DESC) AS group_num
FROM employees;
✔ 데이터를 n개의 그룹으로 나눔 (예: 3등분)
| 함수 | 설명 |
|---|---|
SUM(), AVG(), COUNT() | 그룹 없이 개별 행 유지하며 집계 |
RANK(), DENSE_RANK(), ROW_NUMBER() | 순위 매기기 |
LAG(), LEAD() | 이전/다음 행 값 참조 |
PERCENT_RANK(), CUME_DIST() | 백분율 순위 계산 |
NTILE(n) | 데이터를 n개의 그룹으로 나누기 |