Oracle MODEL 정리 3

Updated:



1. MODEL 기본개념

이번 칼럼도 오라클 MODEL정리 1, 2에 이어서 MODEL 사용법을 계속 알아봅니다. 지난번 칼럼에서는 기본적인 문법, 멀티셀, 싱글셀 개념과 Sequential Order에 대해 알아보았다. 이번 칼럼에서도 여러가지 그룹함수를 이용해서 MODEL절에 대해 더 알아보도록 하겠습니다.

가. 예제 테이블

에제 테이블은 EMP테이블을 가지고 설명합니다. 앞 칼럼에 생성 스크립트와 테이블이 설명되어 있으니 참고하기 바랍니다. EMP테이블을 이용하여 우리가 기존의 ROLLUP방식과 UNION ALL등을 사용하여 문제를 해결했는데 MODEL을 사용하여 똑같은 조회값을 추출할수 있도록 비교 설명하도록 하겠습니다.

나. MODEL예제 3 Formula 권한 부여

EMP 테이블에서 부서별 합계를 구해봅니다. 그러면 아래의 가항에 해당하는 MODEL절이 나올것입니다. 이상태에서 10번 부서만 UPDTAE 권한만 부여하여 CELL이 생성 안되게 할수 있습니다. 이렇게 하는 이유는 불필요한 CELL이 만들어 지는것을 사전에 방지하기 위함입니다.

RULES을 이루고 있는 각 Formula(계산식)마다 이런 권한을 부여할수 있고, 또한 RULES 차원에서 UPDATE, UPSERT(UPDATE + INSERT), UPSERT ALL 을 부여하여 Formula들의 권한을 제어할수 있습니다. 12c DB에서 테스트해본결과 RULES 차원에서 UPDATE를 기술한경우 각부서별 합계 및 총합계 셀이 전부 만들어지지 않으며 UPSERT, UPSERT ALL을 RULES차원에서 기술해주면 각 Formula들이 CELL에 대한 UPSERT 권한을 가진다. 디폴트는 UPSERT ALL입니다.

가. UPSERT ALL SQL
SELECT  DEPTNO, ENAME, SAL
FROM EMP
MODEL
--PARTITION BY ()
DIMENSION BY (DEPTNO,ENAME)
MEASURES (SAL)
RULES --update, upsert, upsert all
(update SAL[NULL, '10번합계'] = SUM(SAL)[DEPTNO=10,ANY],
 SAL[NULL, '20번합계'] = SUM(SAL)[DEPTNO=20,ANY],
 SAL[NULL, '30번합계'] = SUM(SAL)[DEPTNO=30,ANY],
 SAL[NULL, '총합계']   = SUM(SAL)[DEPTNO IN (10,20,30),ANY] 
)
ORDER BY 1, 2, 3 ;

나. UPDATE로 권한제어 SQL
SELECT  DEPTNO, ENAME, SAL
FROM EMP
MODEL
--PARTITION BY ()
DIMENSION BY (DEPTNO,ENAME)
MEASURES (SAL)
RULES --update, upsert, upsert all
(update SAL[NULL, '10번합계'] = SUM(SAL)[DEPTNO=10,ANY],
 SAL[NULL, '20번합계'] = SUM(SAL)[DEPTNO=20,ANY],
 SAL[NULL, '30번합계'] = SUM(SAL)[DEPTNO=30,ANY],
 SAL[NULL, '총합계']   = SUM(SAL)[DEPTNO IN (10,20,30),ANY] 
)
ORDER BY 1, 2, 3 ;

DEPTNO ENAME JOB SAL
10 CLARK MANAGER 2450
10 KING PRESIDENT 5000
10 MILLER CLERK 1300
20 ADAMS CLERK 1100
20 FORD ANALYST 3000
20 JONES MANAGER 2975
20 SCOTT ANALYST 1100
20 SMITH CLERK 800
30 ALLEN SALESMAN 1600
30 BLAKE MANAGER 2850
30 JAMES CLERK 950
30 MARTIN SALESMAN 1250
30 TURNER SALESMAN 1500
30 WARD SALESMAN 1250
    10번합계 8750
    20번합계 8975
    30번합계 9400
    총합계 27125

다. ORA-32638 에러 처리

MODEL정리 2편에서 UNIQUE SINGLE REFERENCE 이라는 옵션을 이야기하였습니다. 이번장에서 좀 더 확실하게 이야기해봅니다. 2편에서 PARTITION BY와 DIMENSION BY 항목에 들어가는 칼럼을 전부 더했을때 각 레코드들이 UNIQUE하게 식별되어야 합니다. 아래의 결과값을 보면 20번부서 1100값과 30번부서 1250 값이 서로 중복되어 있습니다. 이때 UNIQUE SINGLE REFERENCE 옵션을 넣지않으면 아래의 에러를 만나게 됩니다.

ORA-32638 MODEL차원의 주소지정이 고유하지않음

업무적으로 레코드가 UNIQUE 하지 않은 경우라도 MODEL을 사용할려고 한다면, 이 에러때문에 SQL을 사용할수 없으면 안되니 UNIQUE SINGLE REFERENCE 옵션을 사용하여 MODEL이 디폴트로 각 레코드간의 UNIQUE CHECK을 하는것을 막아서 MODEL을 사용할수 있게 합니다. Defalut 값인 UNIQUE DIMENSION 을 사용하면 전체 데이터에 대하여 UNIQUE CHECK 를 합니다. UNIQUE SINGLE REFERENCE 를 사용하면 RULES 절에서 참조되는 ROW에 대해서만 UNIQUE CHECK 를 하지 않습니다.

SELECT  DEPTNO,  SAL, fsales
FROM EMP
MODEL --UNIQUE SINGLE REFERENCE
DIMENSION BY (DEPTNO) 
MEASURES (SAL, sal fsales)
RULES ( fsales[any]= 20 )
ORDER BY 1,2,3;

DEPTNO SAL FSALES
10 1300 20
10 2450 20
10 5000 20
20 800 20
20 1100 20
20 1100 20
20 2975 20
20 3000 20
30 950 20
30 1250 20
30 1250 20
30 1500 20
30 1600 20
30 2850 20

라. MODEL예제 4 CASE IS PRESENT

이번에는 RULES에 CASE와 IS PRESENT를 사용하여 처리 로직을 구현해봅니다. PARTITION BY는 생략되어 있고 DIMENSION BY 에 DEPTNO, JOB이 있습니다. 중복된값이 존재하므로 UNIQUE SINGLE REFERENCE 옵션을 주어 UNIQUE CHECK을 하지 않도록 합니다.

RULES에는 FSALES(ANY, ANY) 가 왼쪽항에 정의되어 있는데 기존 테이블에 없는 CELL이라서 필요한 건수만큼 FSALES 칼럼을 만들어 넣는다. 결과값을 보면 FSALES 칼럼이 만들어진것을 확인할수 있습니다. 우측항을 보면

 CASE WHEN fsales[10,'ER'] IS PRESENT
      THEN fsales[10,'CLERK']
      ELSE 0
      END <br/>

위의 걔산식의 문장을 분석해보면, fsales[10,’ER’] CELL이 있으면 fsales[10,’CLERK’] CELL의 값을 가져오고, 없으면 0 으로 채우라는 이야기입니다. fsales[10,’ER’] CELL이 없으므로 결과값 1처럼 FSALES가 전부 0 으로 처리되어 나온다. 정확한 CELL값인 fsales[10,’MANAGER’] 을 넣게되면 결과값 2번처럼 FSALES가 1300으로 나오는것을 볼수있습니다.

위의 계산식의 문장을 분석해보면, fsales[10,’ER’] CELL이 있으면 fsales[10,’CLERK’] CELL의 값을 가져오고, 없으면 0 으로 채우라는 이야기입니다. fsales[10,’ER’] CELL이 없으므로 결과값 1처럼 FSALES가 전부 0 으로 처리되어 나온다. 정확한 CELL값인 fsales[10,’MANAGER’] 을 넣게되면 결과값 2번처럼 FSALES가 1300으로 나오는것을 볼수있습니다.

가. SQL 1
SELECT  DEPTNO, JOB, sal, fsales
FROM EMP 
MODEL UNIQUE SINGLE REFERENCE 
DIMENSION BY (DEPTNO, JOB) 
MEASURES (sal, sal as fsales)
RULES
( fsales[any,any] = CASE WHEN fsales[10,'ER'] IS PRESENT
                         THEN fsales[10,'CLERK']
                         ELSE 0
                    END )
ORDER BY 1,2,3;

나. SQL 2
SELECT  DEPTNO, JOB, sal, fsales
FROM EMP
MODEL UNIQUE SINGLE REFERENCE 
DIMENSION BY (DEPTNO, JOB) 
MEASURES (sal, sal as fsales)
RULES
( fsales[any,any] = CASE WHEN fsales[10,'MANAGER'] IS PRESENT
                         THEN fsales[10,'CLERK']
                         ELSE 0
   END )
ORDER BY 1,2,3;

가. 1번 SQL 결과값

DEPTNO JOB SAL FSALES
10 CLERK 1300 0
10 MANAGER 2450 0
10 PRESIDENT 5000 0
20 ANALYST 1100 0
20 ANALYST 3000 0
20 CLERK 800 0
20 CLERK 1100 0
20 MANAGER 2975 0
30 CLERK 950 0
30 MANAGER 2850 0
30 SALESMAN 1250 0
30 SALESMAN 1250 0
30 SALESMAN 1500 0
30 SALESMAN 1600 0

나. 2번 SQL결과값

DEPTNO JOB SAL FSALES
10 CLERK 1300 1300
10 MANAGER 2450 1300
10 PRESIDENT 5000 1300
20 ANALYST 1100 1300
20 ANALYST 3000 1300
20 CLERK 800 1300
20 CLERK 1100 1300
20 MANAGER 2975 1300
30 CLERK 950 1300
30 MANAGER 2850 1300
30 SALESMAN 1250 1300
30 SALESMAN 1250 1300
30 SALESMAN 1500 1300
30 SALESMAN 1600 1300

2. 결언

이번 칼럼도 MODEL절에 대한 기본 사용법을 알아보았다. 역시 공대출신의 어쩔수없는 빈약한 글솜씨의 한계를 느끼게 되는 칼럼인것 같습니다. 오늘 UNIQUE SINGLE REFERENCE 옵션을 사용하지 않은경우 만나게되는 에러에 대해 이야기했는데 이 에러를 왜 먼저 이야기 하냐면 개발자들이 이 에러때문에 MODEL공부를 포기하는것을 좀 봤기 때문입니다. 그리고 가능한 쉽게 설명할려고 하다보니 좀 지루해지는 느낌이 듭니다.

이번 칼럼도 MODEL절에 대한 기본 사용법을 알아보았습니다. 역시 공대출신의 어쩔수없는 빈약한 글솜씨의 한계를 느끼게 되는 칼럼인것 같습니다. 오늘 UNIQUE SINGLE REFERENCE 옵션을 사용하지 않은경우 만나게되는 에러에 대해 이야기했는데 이 에러를 왜 먼저 이야기 하냐면 개발자들이 이 에러때문에 MODEL공부를 포기하는것을 봤기 때문입니다. 이미 알고 계신분들의 이해를 바랍니다.