서로 다른 행의 비교나 연산을 위해 만든 함수
SELECT 윈도우함수([대상]) OVER([PARTITION BY 컬럼]
[ORDER BY 컬럼 ASC|DESC]
[ROWS|RANGE BETWEEN A AND B]);
순서 중요!!
1. PARTITION BY
2. ORDER BY
# 파티션이나 누적합이 필요없으면 OVER 를 비워도 됨
SELECT EMPNO, ENAME, SUM(대상) OVER() AS TOTAL FROM EMP;3. ROWS/RANGE
RANGE (DEFAULT)
SELECT R.*, SUM(SAL) OVER(ORDER BY SAL) FROM RANGE_TEST R;
처음부터 현재 행까지
ROWS
값이 같더라도 각 행씩 연산
반드시 BETWEEN A AND B 가 와야 한다.
SELECT R.*,
SUM(SAL) OVER(ORDER BY SAL
ROWS BETWEEN UNBOUNDED PRECEDING
AND CURRENT ROW) AS RESULT1
FROM RANGE_TEST R;
처음부터 현재 행까지
BETWEEN A AND B
시작점 A 정의
마지막 시점 B 정의
CURRENT ROW : 현재행까지 (DEFAULT)
UNBOUNDED FOLLOWING : 마지막까지
N FOLLOWING : N 이후까지
예시 ) 기준이 3번째 행일 때
SELECT R.*,
SUM(SAL) OVER(ORDER BY SAL
ROWS BETWEEN UNBOUNDED PRECEDING
AND 1 FOLLOWING) AS RESULT3
FROM RANGE_TEST R;
처음부터 다음 행까지 누적합
RANK WITHIN GROUP
SELECT RANK(대상) WITHIN GROUP(ORDER BY SAL DESC) AS RANK_VALUE FROM EMP:RANK
SELECT RANK() OVER([PARTITION BY 컬럼]
ORDER BY 컬럼 ASC|DESC);
SELECT ENAME, DEPTNO, SAL,
RANK() OVER(PARTITION BY DEPTNO ORDER BY SAL DESC) AS RANK1
FROM EMP;
SELECT ENAME, DEPTNO, SAL,
RANK() OVER(ORDER BY SAL DESC) AS RANK_VALUE1
FROM EMP;
DENSE_RANK
ROW_NUMBER
예시 ) RANK / DENSE_RANK / ROW_NUMBER 비교하기
SELECT ENAME, DEPTNO, SAL,
RANK() OVER(ORDER BY SAL DESC) AS RANK_VALUE1,
DENSE_RANK() OVER(ORDER BY SAL DESC) AS RANK_VALUE2,
ROW_NUMBER() OVER(ORDER BY SAL DESC) AS RANK_VALUE3,
FROM EMP;
SELECT LAG(컬럼, N) -- 가져올 값을 갖는 컬럼, 몇 번째 값을 가져올지(DEFAULT = 1)
OVER([PARTITION BY 컬럼]
ORDER BY 컬럼 ASC|DESC);
LAG(칼럼명,1,2) -- 칼럼명에서 1 앞의 행을 가져올 지 결정하며, 2는 가져올 값이 NULL일 경우 해당 2로 처리하란 뜻
LEAD(칼럼명,1,2) -- 칼럼명에서 1 이후의 행을 가져올 지 결정하며, 2는 가져올 값이 NULL일 경우 해당 2로 처리하란 뜻
예시 ) 바로 이전 입사자와 급여 비교 (현업에서 많이 사용)
SELECT ENAME, HIREDATE, SAL,
LAG(SAL) OVER(ORDER BY HIREDATE) AS 바로직전상사급여 FROM EMP;
FIRST_VALUE 로 최대값, 최소값 구하기
SELECT ENAME, DEPTNO, SAL,
FIRST_VALUE(SAL) OVER(PARTITION BY DEPTNO ORDER BY SAL) AS MIN_VALUE,
FIRST_VALUE(SAL) OVER(PARTITION BY DEPTNO ORDER BY SAL DESC) AS MAX_VALUE
FROM EMP;
# 기본적으로 RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW 로 정의되어 있음
LAST_VALUE 로 최대값 구하기
SELECT ENAME, DEPTNO, SAL,
LAST_VALUE(SAL) OVER(PARTITION BY DEPTNO ORDER BY SAL) AS MAX_VALUE1,
LAST_VALUE(SAL) OVER(PARTITION BY DEPTNO ORDER BY SAL
RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS MAX_VALUE2
FROM EMP;
# 기본적으로 RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW 로 정의되어 있음
SELECT NTILE(N) OVER([PARTITION BY 컬럼]
ORDER BY 컬럼 ASC|DESC);예시 ) 14명을 2개의 그룹으로 나누기 → 7명씩 나눈다.
SELECT ENAME, SAL, DEPTNO, NTILE(2) OVER(ORDER BY SAL) AS GROUP_NUMBER
FROM EMP;
RATIO_TO_REPORT
RATIO_TO_REPORT(대상) OVER([PARTITION BY 컬럼]);
CUME_DIST
CUME_DIST(대상) OVER([PARTITION BY 컬럼]
ORDER BY 컬럼);
예시 ) RATIO_TO_REPORT / CUME_DIST 비교하기
PERCENT_RANK
PERCENT_RANK(대상) OVER([PARTITION BY 컬럼]
ORDER BY 컬럼);
예시 ) PERCENT_RANK
SELECT ENAME, DEPTNO, SAL, PERCENT_RANK() OVER(ORDER BY SAL)
FROM EMP;