Oracle MODEL 정리 4

Updated:



1. MODEL 기본개념

이번 칼럼도 오라클 MODEL정리 1, 2, 3에 이어서 MODEL 사용법을 계속 알아봅니다. 지난번 칼럼에서는 기본적인 문법인 IS PRESENT에 대해 알아봤습니다. 이번칼럼에는 비슷한 기능인 PRESENTV, PRESENTNNV, GREATEST 함수와 FOR column IN 에 대해 알아봅니다.

가. 예제 테이블

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

나. MODEL예제 5 PRESENTV 와 PRESENTNNV

PRESENTV 와 PRESENTNNV 함수는 비슷한 개념입니다. 그래서 하나만 외우면 될것같습니다.

PRESENTV(CELL, A, B) : CELL값이 존재하면(NULL 이 아니면) A, 아니면 B를 RETURN, =의 오른쪽에서만 사용

PRESENTNNV(CELL, A, B) : CELL 값이 NULL 이면 B, NULL 이 아니면 A 를 RETURN, =의 오른쪽에서만 사용

아래 SQL의 예제를 보면 가와 나항의 결과값으로 Fsales가 모두 1300으로 나타난다. 가번 SQL은 fsales[10,’MANAGER’] CELL이 존재하면 fsales[10,’CLERK’]인 1300을 가져오고 아니면 0을 가져오라는 문구입니다.

나번 SQL은 fsales[10,’MANAGER’] 이 NULL이면 0을 가져오고 아니면 즉 값이 존재하면 fsales[10,’CLERK’] 값인 1300을 가져오라는 이야기입니다. 즉 결과값은 가, 나번 SQL이 동일합니다.

가. PRESENTV 함수
SELECT  DEPTNO, JOB, sal, fsales
FROM EMP
MODEL UNIQUE SINGLE REFERENCE 
DIMENSION BY (DEPTNO,JOB) 
MEASURES (sal, sal as fsales)
RULES
( fsales[any,any] = PRESENTV(fsales[10,'MANAGER'], fsales[10,'CLERK'], 0)
 )
ORDER BY 1,2,3;

나. PRESENTNNV 함수
SELECT  DEPTNO, JOB, sal, fsales
FROM EMP
MODEL UNIQUE SINGLE REFERENCE 
DIMENSION BY (DEPTNO,JOB) 
MEASURES (sal, sal as fsales)
RULES
( fsales[any,any]  = PRESENTNNV(fsales[10,'MANAGER'],  fsales[10,'CLERK'], 0)
  )
ORDER BY 1,2,3;

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

다. MODEL예제 5 GREATEST

GREATEST 함수는 주어진 CELL들을 비교하여 가장 큰값을 반환하는 함수입니다. 비교적 간단한 개념이라 어렵지않게 사용할수 있으리라 생각합니다. 아래의 예제에서 두개의 CELL인 fsales[10,’MANAGER’], fsales[10,’CLERK’]중 큰 값인 fsales[10,’MANAGER’] CELL의 2450을 반환합니다.

GREATEST(CELL_A, CELL_B) : 2개 CELL중 큰 값을 리턴, =의 오른쪽에서만 사용

SELECT  DEPTNO, JOB, sal, fsales
FROM EMP
MODEL UNIQUE SINGLE REFERENCE 
DIMENSION BY (DEPTNO,JOB) 
MEASURES (sal, sal as fsales)
RULES
( fsales[any,any] = GREATEST(fsales[10,'MANAGER'], fsales[10,'CLERK'])
  )
ORDER BY 1,2,3;
DEPTNO JOB SAL FSALES
10 CLERK 1300 2450
10 MANAGER 2450 2450
10 PRESIDENT 5000 2450
20 ANALYST 1100 2450
20 ANALYST 3000 2450
20 CLERK 800 2450
20 CLERK 1100 2450
20 MANAGER 2975 2450
30 CLERK 950 2450
30 MANAGER 2850 2450
30 SALESMAN 1250 2450
30 SALESMAN 1250 2450
30 SALESMAN 1500 2450
30 SALESMAN 1600 2450

라. MODEL예제 6 FOR column IN

FOR column IN 함수는 11G DB의 PIVOT함수를 사용할때 등장합니다. 간단하게 생각하면 가번 SQL처럼 직업이 MANAGER, CLERK인 모든 사람들을 하나씩 나열하여 처리하였는데 이를 FOR column IN 을 이용하여 좀 세련되게 만들었습니다.

나번처럼 중복되는 데이타인 MANAGER와 CLERK을 이용하여 간단한 표현으로 만드는데 이용하였다. 사람이름은 전부이니 ANY로 처리하고 JOB만 MANAGER와 CLERK인 CELL들을 추출해도 동일한 결과값이 나옵니다.

다번은 UPDATE권한을 이용하여 혹시 새로운 CELL이 만들어지는것을 방지하고 ENAME과 JOB을 FOR column IN 방식으로 처리하였다. CV 펑션이 등장하는데 CV() 함수는 포뮬러의 좌측 항에 정의된 멀티셀들을 우측 항으로 복사 하는 기능을 제공하는 매우 강력한 툴입니다. CV는 다음번 칼럼에 자세하게 소개하도록 하겠습니다.

라번처럼 사용해서는 안됩니다. 잘못된값이 발생하므로 치명적인 문제가 발생할수 있습니다.

가. SQL
SELECT   ENAME, JOB, SAL, TRUNC(SAL2)
FROM EMP
MODEL 
DIMENSION BY (ENAME,JOB)   
MEASURES (SAL, 0 SAL2) 
RULES 
(SAL[NULL,'총원' ] =COUNT(SAL)[ANY, ANY],
 SAL[NULL,'합계' ] =SUM(SAL)[ANY, ANY]-SAL[NULL,'총원' ], 
 SAL2['BLAKE','MANAGER' ] = SAL[CV(),CV() ]/SAL[NULL,'총원' ],
 SAL2['CLARK','MANAGER' ] = SAL[CV(),CV() ]/SAL[NULL,'총원' ] ,
 SAL2['JONES','MANAGER' ] = SAL[CV(),CV() ]/SAL[NULL,'총원' ],
 SAL2['ADAMS','CLERK' ]   = SAL[CV(),CV() ]/SAL[NULL,'총원' ] ,
 SAL2['JAMES','CLERK' ]   = SAL[CV(),CV() ]/SAL[NULL,'총원' ] ,
 SAL2['MILLER','CLERK' ]  = SAL[CV(),CV() ]/SAL[NULL,'총원' ],
 SAL2['SMITH','CLERK' ]   = SAL[CV(),CV() ]/SAL[NULL,'총원' ]
 )
ORDER BY 1, 2;

나. SAL2[ANY, FOR JOB IN('MANAGER','CLERK') ] = SAL[CV(),CV() ]/SAL[NULL,'총원' ]

다. UPDATE SAL2[FOR ENAME IN ('ADAMS','BLAKE','CLARK','JAMES','MILLER','SMITH') , 
   FOR JOB I IN('MANAGER','CLERK') ] = SAL[CV(),CV() ]/SAL[NULL,'총원' ] 

라. 잘못사용된 예(Wrong Results 발생)
SAL2[FOR ENAME IN ('ADAMS','BLAKE','CLARK','JAMES','MILLER','SMITH') ,
    FOR JOB IN('MANAGER','CLERK') ] = SAL[CV(),CV() ]/SAL[NULL,'총원' ]    

ENAME JOB SAL SAL2
ADAMS CLERK 1100 78
ALLEN SALESMAN 1600 0
BLAKE MANAGER 2850 203
CLARK MANAGER 2450 175
FORD ANALYST 3000 0
JAMES CLERK 950 67
JONES MANAGER 2975 212
KING PRESIDENT 5000 0
MARTIN SALESMAN 1250 0
MILLER CLERK 1300 92
SCOTT ANALYST 1100 0
SMITH CLERK 800 57
TURNER SALESMAN 1500 0
WARD SALESMAN 1250 0
  총원 14  
  합계 27125  


2. 결언

이번 칼럼은 쉬운 함수와 어려운 함수가 동시에 나온것 같습니다. 갑자기 CV펑션이 나왔는데 이 펑션은 MODEL에서 가장 중요한 역활을 하는 함수중 하나인데 내용이 조금 어려워 다음 칼럼에 이야기 하기로 하겠습니다.