메뉴 건너뛰기

tnt_db

Oracle 선택적조인

운영자 2002.09.18 13:58 조회 수 : 2749 추천:14

CREATE TABLE TEST34(KEY1 VARCHAR2(03),KEY_TYPE VARCHAR2(01),AMT NUMBER);
CREATE UNIQUE INDEX TEST34_I ON TEST34(KEY1);
INSERT INTO TEST34 VALUES ('A01','1',10);
INSERT INTO TEST34 VALUES ('A02','2',20);
INSERT INTO TEST34 VALUES ('A03','1',30);
INSERT INTO TEST34 VALUES ('A04','2',40);
INSERT INTO TEST34 VALUES ('A05','3',50);
INSERT INTO TEST34 VALUES ('A06','3',60);
INSERT INTO TEST34 VALUES ('A07','1',70);
INSERT INTO TEST34 VALUES ('A08','2',80);
INSERT INTO TEST34 VALUES ('A09','1',90);


선택적 조인


조건.
    TEST34 에 다음과 같은 DATA가 있다.

    KEY1 KEY_TYPE AMT
    ---- -------- ----------
    A01  1                10
    A02  2                20
    A03  1                30
    A04  2                40
    A05  3                50
    A06  3                60
    A07  1                70
    A08  2                80
    A09  1                90

문제.
    KEY_TYPE 이 '1','2','3'  3종류로 분류되어있다.
    위의 분류를 A,B 두 분류로 나누어 조회하기를 원한다.
    KEY_TYPE 에 따라  
    '1' 인 경우는 'A'에 더해지고
    '2' 인 경우는 'B'에 더해지며
    '3' 인 경우는 'A','B' 모두에 더해진다.
    따라서 결과에서 나온 총 합은 위의 DATA 총합보다 많은데
    KEY_TYPE 이 '3' 인경우의 합만큼 많게 된다.
    결과가 아래와 같이 나오면 된다.
      
    TYPE AMT  
    ---- ----------
    A           310
    B           250

    A 는 KEY_TYPE '1'과 '3' 의 SUM 이고
    B 는 KEY_TYPE '2'와 '3' 의 SUM 이다.
    단 PLAN 상으로 TEST34에대한 ACCESS 는 한번만 일어나도록
    하여야 한다.

생각.
    가장쉬운 해결책은 무엇이겠는가?.
    우리가 흔히 사용하는 방법이며 가장 일반적인 방법으로
    UNION 을 이용하는 방법이 있을 것이다.
    A를 위한 SELECT 와 B를 위한 SELECT 를 따로 만들어서
    두 DATASET을 UNION ALL 하면 원하는 결과가 나올 것이다.
    
    SELECT 'A' TYPE,
           SUM(AMT) AMT
    FROM   TEST34
    WHERE  KEY_TYPE IN ('1','3')
    UNION ALL
    SELECT 'B',SUM(AMT)
    FROM   TEST34
    WHERE  KEY_TYPE IN ('2','3')
    
   .KEY_TYPE 이라는 조건이 오면 항상
          왼쪽 조건과 같아지게 된다.
          그대로 옮겨보자.

          WHERE T1.KEY_TYPE
              = DECODE(T1.KEY_TYPE,3,T1.KEY_TYPE,T2.R_CNT)
          
    단계5.최종 문장을 보자.      
          SELECT DECODE(T2.R_CNT,1,'A',2,'B') TYPE,
                 SUM(AMT) AMT
          FROM   TEST34 T1,
                (SELECT ROWNUM R_CNT FROM TEST34
                 WHERE  ROWNUM < 3) T2
          WHERE  T1.KEY_TYPE
               = DECODE(T1.KEY_TYPE,3,T1.KEY_TYPE,T2.R_CNT)
          GROUP BY
                 DECODE(T2.R_CNT,1,'A',2,'B')
  
    PLAN :
    SELECT STATEMENT Optimizer=CHOOSE
      SORT (GROUP BY)
        NESTED LOOPS
          VIEW
            COUNT (STOPKEY)
              TABLE ACCESS (FULL) OF TEST34
          TABLE ACCESS (FULL) OF TEST34

    한가지 아쉬운점이 있다면 INDEX COLUMN인 KEY_TYPE 에 DECODE로
    가공이 들어감으로 인해 INDEX SCAN을 하지 못한다는 것이다.
    
뒷풀이.
    결과는 문제에서 요구한 답과 같다.
    단지 UNION으로 해결하면 될 문제를 왜 이렇게 어렵게 끌고
    가느냐고 묻고 싶을지도 모르겠다.
    운이 좋은 경우기 때문에 UNION으로도 풀리는 것이지,
    항상 그런것은 아니다.
    지금은 2개의 QUERY만 UNION으로 엮어 해결이 될 수 있지만,
    상황에 따라 그것이 몇개로 늘어날지 모른다.
    그것을 조건절을 잘 조절해 해결할 수 있다면 어느 방법이
    나은가?.
    스스로 판단해보자.
위로