ANSI/ISO SQL 표준에서 정의한 함수
1. AGGREGATE FUNCTION
GROUP AGGREGATE FUNCTION 이라고도 부릅니다.
COUNT, SUM, AVG, MAX, MIN 외 각종 집계 함수들이 포함됩니다.
집계함수를 제외하고, 소그룹 간의 소계를 계산하는 ROLLUP, GROUP BY 항목들간 다차원적인 소계를 계산하는 CUBE, 특정항목에 대한 소계를 계산하는 GROUPING SETS 함수가 있습니다.
3. WINDOW FUNCTION
분석함수(ANALYTIC FUNCTION)나 순위함수(RANK FUNCTION)로도 알려져 있는 윈도우 함수는 데이터웨어하우스에서 발전된 기능입니다.
그중에서 오늘은 window함수의 범위를 다뤄보자
Window function에 자주 쓰이는 함수로 순위함수, 집계함수, 비율함수 등이 있다.
윈도우 함수종류 | 함수명 | 사용가능 DBMS |
순위(RANK) 관련 | RANK, DENSE_RANK, ROW_NUMBER |
대부분 지원 |
집계(AGGREGATE) 관련 | SUM, MAX, MIN, AVG, COUNT |
SQL Server 경우 Over절 내 Order by 지원 못함 |
순서 관련 함수 | FIRST_VALUE, LAST_VALUE, LAG, LEAD |
ORACLE 만 지원 |
그룹 내 비율 관련 함수 | CUME_DIST, PERCENT_RANK, NTILE, RATIO_TO_REPORT |
PERCENT_RANK 함수는 ANSI/ISO SQL 표준과 Oracle DBMS에서 지원하고 있으며, NTILE 함수는 ANSI/ISO SQL 표준에는 없지만, Oracle, SQL Server에서 지원하고 있다. RATIO_TO_REPORT 함수는 Oracle에서만 지원되는 함수(현업에서 유용). |
선형분석을 포함한 통계분석 함수 | CORR, COVAR_POP, COVAR_SAMP, STDDEV, STDDEV_POP, STDDEV_SAMP, VARIANCE, VAR_POP, VAR_SAMP, REGR_(LINEAR REGRESSION), REGR_SLOPE, REGR_INTERCEPT, REGR_COUNT, REGR_R2, REGR_AVGX, REGR_AVGY, REGR_SXX, REGR_SYY, REGR_SXY | 특화되어있으므로 생략 |
윈도우함수 사용법
윈도우함수(args) OVER (
[ PARTITION BY column ]
[ ORDER BY column [ASC | DESC] ]
[ [ROWS|RANGE] BETWEEN UNBOUNDED PRECEDING[CURRENT ROW]
AND UNBOUNDED FOLLOWING[CURRENT ROW] ]
)
1. 범위지정
범위지정은 over() 안에서 [ RANGE / ROWS ] + BETWEEN 를 지정하여 할 수 있다.
특정 물리적인 행에 대해서 범위를 지정하고 싶다면, ROWS + BETWEEN 을 사용하고,
논리적인 단위로 행의 범위를 지정하고 싶다면, RANGE + BETWEEN 을 사용한다.
ROWS : 물리적인 단위로 행 집합을 지정
RANGE : 논리적인 단위로 의해 행 집합을 지정
BETWEEN ~ AND : 윈도우의 시작과 끝 위치를 지정
UNBOUNDED PRECEDING : 윈도우 시작 위치가 첫 번째 로우임을 의미
UNBOUNDED FOLLOWING : 윈도우 마지막 위치가 마지막 로우임을 의미
[ROW수] PRECEDING : 윈도우 시작 위치가 ROW수만큼 이전이 시작 로우임을 의미
[ROW수] FOLLOWING : 윈도우 마지막 위치가 ROW수만큼 다음이 마지막 로우임을 의미
CURRENT ROW : 현재 로우까지를 의미
예제
윈도우 집계함수와
ROWS + BETWEEN 을 이용한 범위지정
SELECT empno, ename, deptno, sal,
SUM(sal) OVER(ORDER BY deptno, empno
ROWS BETWEEN UNBOUNDED PRECEDING
AND UNBOUNDED FOLLOWING) sal1,
SUM(sal) OVER(ORDER BY deptno, empno
ROWS BETWEEN UNBOUNDED PRECEDING
AND CURRENT ROW) sal2,
SUM(sal) OVER(ORDER BY deptno, empno
ROWS BETWEEN CURRENT ROW
AND UNBOUNDED FOLLOWING) sal3
FROM emp;
-- SAL1 : 첫 번째 ROW부터 마지막 ROW까지의 급여 합계이다.
-- SAL2 : 첫 번째 ROW 부터 현재 ROW까지의 급여 합계이다.
-- SAL3 : 현재 ROW부터 마지막 ROW까지 급여 합계이다.
EMPNO ENAME DEPTNO SAL SAL1 SAL2 SAL3
------ ------- ---------- ---------- ---------- ---------- ----------
7782 CLARK 10 2450 29025 2450 29025
7839 KING 10 5000 29025 7450 26575
7934 MILLER 10 1300 29025 8750 21575
7369 SMITH 20 800 29025 9550 20275
7566 JONES 20 2975 29025 12525 19475
7788 SCOTT 20 3000 29025 15525 16500
7876 ADAMS 20 1100 29025 16625 13500
7902 FORD 20 3000 29025 19625 12400
7499 ALLEN 30 1600 29025 21225 9400
7521 WARD 30 1250 29025 22475 7800
7654 MARTIN 30 1250 29025 23725 6550
7698 BLAKE 30 2850 29025 26575 5300
7844 TURNER 30 1500 29025 28075 2450
7900 JAMES 30 950 29025 29025 950
집계함수 SUM()의 범위를 지정해주는 부분을 통해 확인해보자
SAL1은 ROWS BETWEEN UNBOUNDED PRECEDING (맨 처음) AND UNBOUNDED FOLLOWING (맨 끝)으로
물리적 ROWS가 처음부터 끝까지를 범위로 하여 합을 구해 리턴한다.
(모두 같은 범위를 가지므로 합은 단일값으로 나온다)
SAL2는 ROWS BETWEEN UNBOUNDED PRECEDING (맨 처음) AND CURRENT ROW (현재 함수실행되는 로우) 까지
물리적 ROW가 맨처음부터 SUM을 해주는 부분까지 누적합을 구하는 식이 되는것이다.
SAL2는 그와 반대로
ROWS BETWEEN CURRENT ROW (현재 함수실행되는 로우) AND UNBOUNDED FOLLOWING (맨 끝) 으로
총합에 대해서 앞부분의 값을 제외하는 형식처럼 나오게 된다.
이해가 되는가?
이번에는 RANGE 예를 보자!
윈도우 집계함수와
ROWS + BETWEEN 을 이용한 범위지정
WITH test AS
(
SELECT '200801' yyyymm, 100 amt FROM dual
UNION ALL SELECT '200802', 200 FROM dual
UNION ALL SELECT '200803', 300 FROM dual
UNION ALL SELECT '200804', 400 FROM dual
UNION ALL SELECT '200805', 500 FROM dual
UNION ALL SELECT '200806', 600 FROM dual
UNION ALL SELECT '200808', 800 FROM dual
UNION ALL SELECT '200809', 900 FROM dual
UNION ALL SELECT '200810', 100 FROM dual
UNION ALL SELECT '200811', 200 FROM dual
UNION ALL SELECT '200812', 300 FROM dual
)
SELECT yyyymm
, amt
, SUM(amt) OVER(ORDER BY TO_DATE(yyyymm,'yyyymm')
RANGE BETWEEN INTERVAL '3' MONTH PRECEDING
AND INTERVAL '1' MONTH PRECEDING) amt_pre3
, SUM(amt) OVER(ORDER BY TO_DATE(yyyymm,'yyyymm')
RANGE BETWEEN INTERVAL '1' MONTH FOLLOWING
AND INTERVAL '3' MONTH FOLLOWING) amt_fol3
FROM test
;
-- AMT_PRE3 : 직전 3개월 합계
-- AMT_FOL3 : 이후 3개월 합계
YYYYMM AMT AMT_PRE3 AMT_FOL3
--------- ---------- ---------- ----------
200801 100 900
200802 200 100 1200
200803 300 300 1500
200804 400 600 1100
200805 500 900 1400
200806 600 1200 1700
200808 800 1100 1200
200809 900 1400 600
200810 100 1700 500
200811 200 1800 300
200812 300 1200
RANGE에 대한 설명은 추가로 하지않아도 될것같다.
논리적인 인터발을 주거나, 값에 대한 합계를 좀더 다양하게 활용할수있다.
+
Q. range / rows에 같은 범위를 주어도 차이가 없나요?
SELECT C1,C2,SUM(TEST2.C2) OVER(ORDER BY C1 range BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS 합 FROM TEST2
SELECT C1,C2,SUM(TEST2.C2) OVER(ORDER BY C1 rows BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS 합 FROM TEST2
집계함수의 기준의 되는값이 같은 값을 같는경우
rows 는 물리적으로 다른 행으로 취급하여, 순서대로 SUM함수를 태우지만,
Range는 논리적으로 기준값이 같은 Row들은 하나의 그룹으로 취급하여, SUM의 값을 반환해준다.
'Work > DataBase' 카테고리의 다른 글
[SQLD] 계층형 질의와 셀프조인 (0) | 2020.05.31 |
---|---|
[SQLD] 조인원리 NL join, Sort-Merge join, Hash Join (0) | 2020.05.29 |
[SQLD] Delete, Truncate, Drop 비교 (0) | 2020.05.29 |
[ORACLE] DB dump 백업 및 복구 (export / emport ) (0) | 2020.05.28 |
[SQLD] SQLD 최신 기출 문제 , 요약 , 책 , 사이트 총정리 (29) | 2020.05.15 |