2. 핵심 원리
2.1 OVER 절의 세 부분
집계함수(컬럼) OVER (
PARTITION BY 그룹 컬럼 -- 생략하면 전체가 한 그룹
ORDER BY 정렬 컬럼 -- 생략하면 순서 없음
ROWS|RANGE BETWEEN 시작 AND 끝 -- 프레임, 생략하면 기본값
)| 부분 | 하는 일 | 생략하면 |
|---|---|---|
PARTITION BY |
행을 그룹으로 나눈다 | 전체가 한 그룹 |
ORDER BY |
그룹 안의 행 순서를 정한다 | 그룹 전체가 프레임 |
| 프레임 | 각 행이 집계에 쓰는 범위 | 아래 2.2절의 기본값 |
OVER () 처럼 괄호를 비워 두면 전체 행이 하나의 그룹이 되어, 모든 행에 같은 전체 합계가 붙습니다. 이 값으로 비율(amt * 100.0 / SUM(amt) OVER ())을 구합니다.
2.2 프레임과 기본값
프레임은 "현재 행을 기준으로 집계에 넣을 행의 범위"입니다. 범위의 양 끝은 다음 다섯 가지 중에서 고릅니다.
| 경계 | 뜻 |
|---|---|
UNBOUNDED PRECEDING |
그룹의 첫 행 |
n PRECEDING |
현재 행보다 n행 앞 |
CURRENT ROW |
현재 행 |
n FOLLOWING |
현재 행보다 n행 뒤 |
UNBOUNDED FOLLOWING |
그룹의 마지막 행 |
OVER 에 ORDER BY 만 쓰고 프레임을 생략하면, 기본 프레임은 RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW 입니다. 표준이며 Oracle·Tibero·MySQL·MSSQL 이 모두 같습니다. 그래서 SUM(amt) OVER (ORDER BY ord_date) 는 첫 행부터 현재 행까지의 누적합이 됩니다.
2.3 ROWS 와 RANGE 의 차이
ROWS 는 정렬된 행의 위치를 세고, RANGE 는 ORDER BY 값이 같은 행(동점 행)을 한 덩어리로 봅니다.
| 구분 | 기준 | 같은 정렬 값의 행 |
|---|---|---|
ROWS |
물리적 행 위치 | 하나씩 따로 더한다 |
RANGE |
정렬 값의 범위 | 함께 더한다 |
핵심기본 프레임이
RANGE라서, 정렬 기준이 같은 행이 2건이면 두 행 모두 "그 값까지 전부 더한 합계"를 받습니다. 행 단위 누적합이 필요하면ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW를 명시하고,ORDER BY에 유일한 컬럼(id)을 덧붙입니다.
2.4 DB 별 지원 범위
| 기능 | Oracle·Tibero | MySQL | MSSQL |
|---|---|---|---|
| 윈도 함수 | Oracle 8i 부터, Tibero 지원 | 8.0 부터 | 2005 부터 |
OVER (PARTITION BY) 집계 |
지원 | 8.0 부터 | 2005 부터 |
집계의 OVER (ORDER BY)·프레임 |
지원 | 8.0 부터 | 2012 부터 |
RANGE 숫자·INTERVAL 오프셋 |
가능 | 8.0 부터 가능 | 불가 |
RATIO_TO_REPORT |
지원 | 없음 | 없음 |
MSSQL 은 2005 에 OVER (PARTITION BY) 집계만 되고, 집계 함수의 누적합(OVER (ORDER BY))과 ROWS·RANGE 프레임은 2012 부터 됩니다. MSSQL 의 RANGE 는 UNBOUNDED·CURRENT ROW 만 허용하고 RANGE 3 PRECEDING 같은 숫자 오프셋은 쓸 수 없습니다.