메뉴 건너뛰기

tnt_db

Oracle PARAMETER값 변경에따른 유연한 GROUP BY

운영자 2002.09.18 14:27 조회 수 : 4127 추천:27

CREATE  TABLE TEST08 (부문 VARCHAR2(5) NOT NULL,
                      부서 VARCHAR2(5) NOT NULL,
                      직급 VARCHAR2(2) NOT NULL,
                      지역 VARCHAR2(6) NOT NULL,
                      직원수 NUMBER,
                      CONSTRAINT TEST08_PK PRIMARY KEY (부문,부서,직급,지역)
                     );
INSERT INTO TEST08
SELECT SITE,DEPT,LEV,LOCAL,DECODE(MOD(ROWNUM,2),0,2,1)
FROM  (SELECT 'SITE1' SITE FROM DUAL UNION ALL SELECT 'SITE2' SITE FROM DUAL) A,
(SELECT 'DEPT1' DEPT FROM DUAL UNION ALL SELECT 'DEPT2' DEPT FROM DUAL UNION ALL
  SELECT 'DEPT3' DEPT FROM DUAL UNION ALL SELECT 'DEPT4' DEPT FROM DUAL) B,
(SELECT '서울' LOCAL FROM DUAL UNION ALL SELECT '경기' LOCAL FROM DUAL UNION ALL
  SELECT '경상' LOCAL FROM DUAL UNION ALL SELECT '전라' LOCAL FROM DUAL) C,
(SELECT 'A'  LEV FROM DUAL UNION ALL SELECT 'B'  LEV FROM DUAL UNION ALL
  SELECT 'C'  LEV FROM DUAL) D;


Parameter 값의 변동에 따른 유연한 Group By

조건.
    TABLE : TEST08
    ------------------------------------
    부문                      VARCHAR2(5)
    부서                      VARCHAR2(5)
    직급                      VARCHAR2(2)
    지역                      VARCHAR2(6)
    직원수                    NUMBER

    부문  부서  직급 지역     직원수    
    ----- ----- ---- ------ --------
    SITE1 DEPT1 A    서울          2
    SITE2 DEPT1 A    서울          1
    SITE1 DEPT1 B    서울          1
    SITE2 DEPT3 B    서울          1
    SITE2 DEPT2 C    서울          2
    SITE2 DEPT3 C    서울          2
    SITE1 DEPT2 A    경기          2
    SITE2 DEPT3 C    경상          1
    SITE2 DEPT2 A    전라          1
    SITE1 DEPT3 B    서울          1
    SITE1 DEPT4 B    서울          1
    SITE1 DEPT4 C    서울          2
    SITE2 DEPT1 A    경기          2
    SITE1 DEPT4 C    경상          1
    SITE1 DEPT1 A    전라          1
      
    점점점......  

문제.
    STORED PROCEDURE 또는 일반 APPLICATION PROGRAM 중
    다음과 같은 경우가 발생한다.
    PARAMETER 값이 하나 또는 그이상 들어오는데 그 순서대로
    TEST08의 DATA를 GROUP지어 직원수의 SUM을 보고싶다.
    TEST08의 경우 4개의 GROUP BY 인자가 있으므로 PARAMETER1 ~ 3
    까지가 들어온다고 가정하면,
    PARAM1,PARAM2,PARAM3를 PARAMETER로 받는다.
    예를들어, PARAMETER 순서대로 부문,부서,직급이 들어오면
    그 순서대로 GROUP 지은 직원수가 나와야하고,
    부서,직급이 들어오면 두개만,부서만 들어오면 부서별로만
    GROUP을 지어 그직원수의 합을 보여주는 문장을 하나의 SQL로
    만들고 싶다.

생각.
    말 그대로 GROUP BY 될 순서및 인자가 상황에 따라서 바뀐다.
    그때마다 각 경우의 수를 따져서 IF를 만들고 하나의 IF에
    하나의 GROUP BY 된 SQL 을 달아주는 것도 비 효율적이다.
    한번에 해결하자느게 목표다.
    엿보기1.IF 로 조건 분기가 가능한 현상은 SELECT 절에서
            대부분 DECODE로 해결이 가능하다.
    엿보기2.SELECT절에서 IF가 사용 가능하다면 다음과 같이 될 것이다.
    
            SELECT
                  IF    PARAM1 = 부문 THEN  부문
                  ELSIF PARAM1 = 부서 THEN  부서
                  ELSIF PARAM1 = 직급 THEN  직급
                  ELSE  PARAM1 = 지역 THEN  지역 GR1,
                  IF    PARAM2 = 부문 THEN  부문
                  ELSIF PARAM2 = 부서 THEN  부서
                  ELSIF PARAM2 = 직급 THEN  직급
                  ELSE  PARAM2 = 지역 THEN  지역 GR2,
                  IF    PARAM3 = 부문 THEN  부문
                  ELSIF PARAM3 = 부서 THEN  부서
                  ELSIF PARAM3 = 직급 THEN  직급
                  ELSE  PARAM3 = 지역 THEN  지역 GR3,
                  SUM(직원수)
           FROM   TEST08
           GROUP BY 1,2,3;

해법.
    아주 간단하다.
    길게 생각할 필요도 없이 있는 기능을 그냥 이용하면된다.
    단지 이렇게도 이용을 할 수가 있다는 것이 요점일 뿐이다.
    엿보기에 있는 문장을 DATABASE가 알아먹게 바꿔만 주면 답이다.
    단계1.바꿔보자,
      
          SELECT DECODE('부문','부문',부문,
                               '부서',부서,
                               '직급',직급,
                               '지역',지역)  GR1,
                 DECODE('직급','부문',부문,
                               '부서',부서,
                               '직급',직급,
                               '지역',지역)  GR2,
                 DECODE('지역','부문',부문,
                               '부서',부서,
                               '직급',직급,
                               '지역',지역)  GR3,
                 SUM(직원수)  직원수
          FROM   TEST08
          GROUP BY
                 DECODE('부문','부문',부문,
                               '부서',부서,
                               '직급',직급,
                               '지역',지역),
                 DECODE('직급','부문',부문,
                               '부서',부서,
                               '직급',직급,
                               '지역',지역),
                 DECODE('지역','부문',부문,
                               '부서',부서,
                               '직급',직급,
                               '지역',지역)
          이게 전부다.

뒷풀이 .
    각 경우를 살펴보자
    먼저 PARAM1,2,3에 각각 '부문','직급','지역' 이 들어오면
    어떻게 되나?.

    SELECT  부문  GR1,
            직급  GR2,
            지역  GR3,
            SUM(직원수)  직원수
    FROM    TEST08
    GROUP BY
            부문,직급,지역
    위와 같이 되어서 다음과 같은 답이 나올 것이다.
  
    GR1   GR GR3    직원수    
    ----- -- ------ ----------
    SITE1 A  경기            4
    SITE1 A  경상            4
    SITE1 A  서울            4
    SITE1 A  전라            4
    SITE1 B  경기            4
    SITE1 B  경상            4
    SITE1 B  서울            4
    SITE1 B  전라            4
    SITE1 C  경기            4
    SITE1 C  경상            4
    SITE1 C  서울            4
    SITE1 C  전라            4
    SITE2 A  경기            8
    SITE2 A  경상            8
    SITE2 A  서울            8
    SITE2 A  전라            8
    SITE2 B  경기            8
    SITE2 B  경상            8
    SITE2 B  서울            8
    SITE2 B  전라            8
    SITE2 C  경기            8
    SITE2 C  경상            8
    SITE2 C  서울            8
    SITE2 C  전라            8

    반면, PARAM1,2,3에 각각 '부문','지역',NULL 이 들어오면
    어떻게 되나?.
          다시말해서 부문별/지역별 합을 보고싶은 경우이다.

    SELECT  부문  GR1,
            지역  GR2,
            NULL  GR3,
            SUM(직원수)  직원수
    FROM    TEST08
    GROUP BY
            부문,지역,NULL
    위와 같이 되어서 다음과 같은 답이 나올 것이다.

    GR1   GR2     직원수    
    ----- ------  ----------
    SITE1 경기            12
    SITE2 경기            24
    SITE1 경상            12
    SITE2 경상            24
    SITE1 서울            12
    SITE2 서울            24
    SITE1 전라            12
    SITE2 전라            24
    
    그런대로 멋있는 기능이다.
    GROUP BY 에 DECODE를 썼을경우와 그렇지 않은경우의
    PLAN 상의 차이는 없다.
    PLAN에 영향을 미치는것은 RULE-BASED OPTIMIZER MODE 에서
    주로 WHERE 절이기 때문이다.
    이런 기능하나로 줄일 수 있는 일의 양이 SYSTEM에따라 다르겠지만
    분명히 있다는 것이다.
    열심히 알아둬서 손해볼 건 없다는 사실을 다시한번 상기하기를...
위로