Home 14. 분석함수
Post
Cancel

14. 분석함수

분석함수는 집계 함수의 확장 기능으로 생각할 수 있다. 집계 함수는 행 그룹으로 값을 집계하고, 분석 함수는 파티션과 윈도우로 값을 집계한다.

집계 함수는 행 그룹 별로 단일 행을 반환하기 때문에 데이터 집합이 변경되지만, 분석 함수는 데이터 집합을 변경하지 않고 값을 집계한다. 데이터 집합이 변경되지 않기 때문에 원본 값과 집계 값을 함께 분석할 수 있는 장점이 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
# 집계 함수를 사용한 버전
SELECT a.empno, a.sal, b.sal AS c1, a.sal / b.sal AS c2
FROM emp a,
    (SELECT deptno, SUM(sal) AS sal FROM emp GROUP BY deptno) b
WHERE a.deptno = 10
AND b.deptno = a.deptno
ORDER BY 1;

# 분석 함수를 사용한 버전
SELECT empno, sal, SUM(sal) OVER () AS c1, RETIO_TO_REPORT(sal) OVER () AS c2
FROM emp
WHERE deptno = 10
ORDER BY 1;

14.1 기본 문법

분석 함수는 OVER 키워드를 사용한다. 집계 함수에 OVER 키워드를 기술하면 분석 함수로 동작한다.

OVER 키워드에는 ANALYTIC 절을 기술할 수 있고, 이 절은 QUERY PARTITION 절, ORDER BY 절, WINDOWING 절로 구성된다.

14.1.1 QUERY PARTITION 절

QUERY PARTITION 절은 GROUP BY 절과 유사하게 동작한다. QUERY PARTITION 절을 생략하면 전체 행이 하나의 파티션으로 동작한다.

1
2
3
4
5
6
SELECT empno, job, sal
      , SUM(sal) OVER (PARTITION BY job) AS c1 -- job별 합계
      , SUM(sal) OVER () AS c2 -- 총 합계
FROM emp
WHERE deptno = 30
ORDER BY 2, 1;

14.1.2 ORDER BY 절

1
2
3
4
SELECT empno, sal, SUM(sal) OVER (ORDER BY sa1, empno) AS c1
FROM emp
WHERE deptno = 30
ORDER BY 2, 1;

14.1.3 WINDOWING 절

WINDOWING 절로 파티션의 윈도우를 지정할 수 있다. 윈도우는 ROWS 방식이나 RANGE 방식으로 지정할 수 있다.

[윈도우 범위를 지정하는 키워드]

  • BETWEEN … AND … : 윈도우의 시작과 끝
  • UNBOUNDED PRECEDING : 앞쪽 끝
  • UNBOUNDED FOLLOWING : 뒤쪽 끝
  • CURRENT ROW : 현재 행
  • value_expr PRECEDING : ROWS - 현재 행에서 앞쪽으로 value_expr 만큼 이동, RANGE - 현재 값에서 value_expr 을 가감
  • value_exp FOLLOWING : ROWS - 현재 행에서 뒤쪽으로 value_expr 만큼 이동, RANGE - 현재 값에서 value_expr 을 가감

341~350p

14.1.4 KEEP 키워드

KEEP 키워드를 사용하면 ANALYTIC 절에 QUERY PARTITION 절만 사용할 수 있다.

1
2
3
4
5
# job 파티션 별 sal가 최소인 행을 대상으로 comm의 최고값을 조회
SELECT ename, job, sal, comm, MAX(comm) KEEP(DENSE_RANK FIRST ORDER BY sal) OVER (PARTITION BY job) AS c1
FROM emp
WHERE deptno = 30
ORDER BY 2,3,4;

14.1.5 주의사항

  1. RANGE 방식에 value_expr을 지정하면 ORDER BY 절에 숫자 값이나 날짜 값을 사용해야 한다
  2. RANGE 방식에 value_expr을 지정하면 정렬 표현식을 1개만 사용할 수 있다
  3. 분석함수는 SELECT 절과 ORDET BY 절에 사용할 수 있다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 1번 주읫사항
SELECT job, sal, sum(sal) OVER (ORDER BY job RANGE 1 PRECEDING) as c1
FROM emp
WHERE deptno = 30;

# 2번 주의사항
SELECT job, sal, SUM(sal) OVER (ORDER BY sal, comm RANGE 1 PRECEDING) as c1
FROM emp
WHERE deptno = 30;

# 3번 주의 사항
SELECT deptno, ename, sal
FROM emp
WHERE SUM(sal) OVER (PARTITION BY deptno) >= 1000;

14.2 분석 함수

분석 함수의 대부분은 집계 함수에 OVER 키워드를 기술하는 방식으로 사용한다.

14.2.1 기본 함수

  • COUNT 함수 : 전체 행의 개수나 expr의 개수를 반환
  • MIN 함수 : expr의 최저 값을 반환
  • MAX 함수 : expr의 최고 값을 반환
  • SUM 함수 : expr의 합계 값을 반환
  • AVG 함수 : expr의 평균 값을 반환 (358~361p)

14.2.2 통계 함수

  • STDDEV 함수 : expr의 표준 편차를 반환
  • VARIANCE 함수 : expr의 분산을 반환

이외에도 다음의 통계 함수를 분석 함수로 사용할 수 있다.

14.2.3 순위 함수

순위 함수는 정렬 조건에 따른 순위를 반환한다. 순위 집계함수는 가상의 행을 생성하지만 순위 분석 함수는 실제의 행으로 값을 계산한다.

  • RANK 함수 : expr이 동일하면 동순위를 부여하고 다음 순위는 동순위의 개수만큼 건너뛴다.
  • DENSE_RANK 함수 : 동순위가 존재하더라도 다음 순위를 이어서 부여한다.
  • ROW_NUMBER 함수 : 고유한 순번을 반환, 정렬 값이 동일하더라도 다른 순번을 부여하기 때문에 결과 값이 변경될 수 있다.
  • NTILE 함수 : order_by_clause에 따라 행을 정렬하고, expr의 개수만큼 버킷을 생성한 후 행에 해당하는 버킷 번호를 할당한다. NTILE 함수로 생성한 버킷으로 행을 집계할 수 있다. 367~369p
1
2
3
4
5
6
7
8
9
# 950~1250 1번 버킷, 1500~2850 2번 버킷...
SELECT sal
     , NTILE(1) OVER (ORDER BY sal) AS c1, NTILE(2) OVER (ORDER BY sal) AS c2
     , NTILE(3) OVER (ORDER BY sal) AS c3, NTILE(4) OVER (ORDER BY sal) AS c4
     , NTILE(5) OVER (ORDER BY sal) AS c5, NTILE(6) OVER (ORDER BY sal) AS c6
     , NTILE(7) OVER (ORDER BY sal) AS c7
FROM emp
WHERE deptno = 30
ORDER BY 1;
  • CUME_DIST 함수 : 누적 분포 값을 반환한다. (0 < y <= 1)
  • PERCENT_RANK 함수 : 백분위 순위 값을 반환한다. (0 <= y <= 1)
  • RATIO_TO_REPORT 함수 : expr의 합계에 대한 현재 expr의 비율을 반환한다.

14.2.4 분포 함수

분포 함수는 분포 모형에 따른 분포 값을 반환한다.

  • PERCENTILE_COUNT 함수 : 연속 분포 모델에서 expr에 지정한 백분위 값에 해당하는 값을 반환한다.
  • PERCENTILE_DISC 함수 : 이산 분포 모델에서 expr에 지정한 백분위 값에 해당하는 값을 반환한다.
  • MEDIAN 함수 : 연속 분포 모형을 가진 중앙값을 반환한다.

14.2.5 순차 함수

순차에 해당하는 값을 가져오는 함수다.

  • FIRST_VALUE 함수 : 윈도우 첫 행의 expr을 반환한다.
  • LAST_VALUE 함수 : 윈도우 끝 행의 expr을 반환한다.
  • NTH_VALUE 함수 : 윈도우 n번째 행의 measure_expr을 반환한다.

14.2.6 기타 함수

  • LAG 함수 : 현재 행에서 offset 이전 행의 value_expr을 반환한다.
  • LEAD 함수 : 현재 행에서 offset 이후 행의 value_expr을 반환한다.

LAG 함수와 LEAD 함수는 행 기준으로 동작하므로 분석 함수의 정렬 값이 고유하지 않으면 값이 무작위로 변경될 수 있다.

  • LISTAGG 함수 : measure_expr을 order_By_clause로 정렬한 후 delimiter로 구분하여 연결한 값을 반환한다.

14.3 활용 예제

선분 이력 전환 1

점 이력을 선분 이력으로 전환해보자

1
2
3
4
5
-- LEAD 함수를 사용하면 점 이력을 선분 이력으로 변환할 수 있다.
SELECT cd, dt AS bg_dt
      , LEAD(dt - 1, 1, DATE, '9999-12-31') OVER (ORDER BY dt) AS ed_dt, v1
FROM t1
ORDER BY 1, 2;

선분 이력 전환 2

월별 이력을 선분 이력으로 전환해보자

1
2
3
4
5
6
7
8
9
10
-- ROW_NUMBER 함수로 생성한 순번의 차를 이용하여 행 그룹을 생성
SELECT cd, MIN(ym) AS bg_ym
      , CASE WHEN MAX(r1) = MAX(cn) THEN '999912' ELSE MAX(ym) END AS ed_ym, v1
FROM (SELECT a.*
        , COUNT(*) OVER (PARTITION BY a.cd) AS cn
        , ROW_NUMBER() OVER (PARTITION BY a.cd ORDER BY a.ym) AS r1
        , ROW_NUMBER() OVER (PARTITION BY a.cd, a.v1 ORDER BY a.ym) AS r2
        FROM t1 a)
GROUP BY cd, v1, r1 - r2
ORDER BY 1, 2;

선분 이력 병합

1
2
3
4
5
6
7
SELECT cd, MIN(bg) AS bg, MAX(ed) AS ed, yn
FROM(SELECT a.*
      , ROW_NUMBER() OVER (PARTITION BY cd ORDER BY bg) AS r1
      , ROW_NUMBER() OVER (PARTITION BY cd, yn ORDER BY bg) AS r2
      FROM t1 a)
GROUP BY cd, yn, CASE WHEN yn = 'N' THEN r1 - r2 ELSE r1 END
ORDER BY 1, 2;

행 패턴 검색

1
2
3
4
5
6
7
8
9
WITH w1 AS (
  SELECT a.*
      , NVL (SIGN (v1 - LAG(v1) OVER (PARTITION BY cd ORDER BY dt)), 0) AS df
  FROM t1 a)
  SELECT a.*
      , ROw_NUMBER() OVER (PARTITION BY cd ORDER BY dt) AS r1
      , ROw_NUMBER() OVER (PARTITION BY cd, df ORDER BY dt) AS r2
  FROM w1 a
ORDER BY 1m 2;

선형 보간

행 복제 기법을 사용하여 데이터가 존재하지 않는 구간의 행을 생성하고, LEAD 함수를 사용하여 보간 값을 계산한다.

1
2
3
4
5
6
7
8
9
10
SELECT a.dt + b.lv - 1 AS dt,
      ROUND (a.v1 + (a.v1_df / a.dn) * (b.lv - 1), 2) AS v1
FROM (SELECT a.*,
        NVL(LEAD(a.v1) OVER (ORDER BY a.dt) - a.v1, 0) AS v1_df,
        NVL(LEAD(a.dt) OVER (ORDER BY a.dt) - a.dt, 0) AS dn
      FROM t1 a) a,
      (SELECT LEVEL AS 1v FROM DUAL CONNECT BY LEVEL <=10)b
WHERE b.1v <= a.dn
ORDER BY 1,

This post is licensed under CC BY 4.0 by the author.

13. 집합 연산자

01. 알아두어야 할 시스템, 인프라 지식