메뉴 건너뛰기

tnt_db

Oracle 상호간 OUTER 조인의 해결방안

운영자 2002.09.18 14:00 조회 수 : 2941 추천:11

CREATE TABLE TEST30 (KEY1 VARCHAR2(02),AMT NUMBER);
CREATE INDEX TEST30_I ON TEST30(KEY1);
INSERT INTO TEST30 VALUES ('A',123);
INSERT INTO TEST30 VALUES ('B',345);
INSERT INTO TEST30 VALUES ('C',357);
INSERT INTO TEST30 VALUES ('D',763);
INSERT INTO TEST30 VALUES ('E',843);
INSERT INTO TEST30 VALUES ('F',345);
INSERT INTO TEST30 VALUES ('G',235);
INSERT INTO TEST30 VALUES ('H',845);
INSERT INTO TEST30 VALUES ('I',652);
INSERT INTO TEST30 VALUES ('J',323);
CREATE TABLE TEST31 (KEY1 VARCHAR2(02),YM VARCHAR2(06), AMT1 NUMBER);
CREATE INDEX TEST31_I ON TEST31(KEY1,YM);
INSERT INTO TEST31 VALUES ('A','199905',23);
INSERT INTO TEST31 VALUES ('A','199906',43);
INSERT INTO TEST31 VALUES ('A','199907',56);
INSERT INTO TEST31 VALUES ('B','199906',23);
INSERT INTO TEST31 VALUES ('B','199907',43);
INSERT INTO TEST31 VALUES ('C','199908',56);
CREATE TABLE TEST32 (KEY1 VARCHAR2(02),YM VARCHAR2(06), AMT2 NUMBER);
CREATE INDEX TEST32_I ON TEST32(KEY1,YM);
INSERT INTO TEST32 VALUES ('B','199905',33);
INSERT INTO TEST32 VALUES ('C','199906',65);
INSERT INTO TEST32 VALUES ('D','199907',87);
INSERT INTO TEST32 VALUES ('D','199908',12);
INSERT INTO TEST32 VALUES ('E','199907',45);
INSERT INTO TEST32 VALUES ('E','199908',89);
CREATE TABLE TEST33 (KEY1 VARCHAR2(02),YM VARCHAR2(06), AMT3 NUMBER);
CREATE INDEX TEST33_I ON TEST33(KEY1,YM);
INSERT INTO TEST33 VALUES ('B','199905',76);
INSERT INTO TEST33 VALUES ('C','199906',98);
INSERT INTO TEST33 VALUES ('E','199907',21);
INSERT INTO TEST33 VALUES ('F','199908',54);
INSERT INTO TEST33 VALUES ('G','199907',87);
INSERT INTO TEST33 VALUES ('H','199908',85);



상호간 OUTER 조인의 해결방안

조건.
    TEST30

    열 이름   유형
    --------- ----
    KEY1      VARCHAR2(2)
    AMT       NUMBER
    KEY1 AMT
    ---- --------
    A         123
    B         345
    C         357
    D         763
    E         843
    F         345
    G         235
    H         845
    I         652
    J         323    

    TEST31                  TEST32                  TEST33
  
    열 이름   유형          열 이름   유형          열 이름   유형
    --------- ----          --------- ----          --------- ----
    KEY1      VARCHAR2(2)   KEY1      VARCHAR2(2)   KEY1      VARCHAR2(2)
    YM        VARCHAR2(6)   YM        VARCHAR2(6)   YM        VARCHAR2(6)
    AMT1      NUMBER        AMT2      NUMBER        AMT3      NUMBER


    KEY1 YM     AMT1        KEY1 YM     AMT2        KEY1 YM     AMT3
    ---- ------ ------      ---- ------ ------      ---- ------ ------
    A    199905     23      B    199905     33      B    199905     76
    A    199906     43      C    199906     65      C    199906     98
    A    199907     56      D    199907     87      E    199907     21
    B    199906     23      D    199908     12      F    199908     54
    B    199907     43      E    199907     45      G    199907     87
    C    199908     56      E    199908     89      H    199908     85

문제.
    TEST30의 KEY1을 FOREIGN KEY 로
    TEST31부터 TEST33 까지가 KEY1과 YM을 PRIMARY KEY로 가지고 있는
    다른 성격의 DATA를 관리하는 같은 구조의 테이블이다.
    TEST31부터 TEST33까지에 DATAT가 존재하면 존재하는 모든 DATA를
    YM과 KEY1순으로 정렬 하여
    TEST30.AMT, TEST31.AMT1, TEST32.AMT2, TEST33.AMT3
    을 보고싶다.
    결과가 다음과 같이 나오면 되겠다.

    YM     KEY1 AMT        AMT1       AMT2       AMT3
    ------ ---- ---------- ---------- ---------- ----------
    199905 A           123         23
    199905 B           345                    33         76
    199906 A           123         43
    199906 B           345         23
    199906 C           357                    65         98
    199907 A           123         56
    199907 B           345         43
    199907 D           763                    87
    199907 E           843                    45         21
    199907 G           235                               87
    199908 C           357         56
    199908 D           763                    12
    199908 E           843                    89
    199908 F           345                               54
    199908 H           845                               85


생각.
    실제 설계에서는 피해가는 부분이지만 어쩔 수 없이 위와 같이
    설계가 이루어지는 경우가 있다.
    조건식에서 양방향 OUTER JOIN을 이용할 수 있다면 혹시 쉽게
    해결할 수 있는 문제일지 모른다.
    하지만 불행하게도 양방향 OUTER JOIN 은 먹혀들지를 않는다.
    MASTER인 TEST30을 기준으로 OUTER 조인을 사용할 것인가?..
    KEY1만 이라면 그렇게 할 수도 있을 것이다.
    하지만 YM에 대해서는 또 어떻게 할 것인가?.
    앞 주제중에 구조 DATA를 이용하는 주제가 있었다.
    해결 방법은 그 방법과 흡사하다.
    KEY1과 YM을 먼저 만들어 놓고 그것을 기준으로 OUTER 조인을
    사용하면 된다.
    복습하는 셈 치고 한번 직접 해보자.
    결코 어려운 문제가 아니다.
    
해법.TEST31 부터 TESTT33 사이에 존재하는 KEY과  YM을 먼저 만들어보자.
     31부터 33까지에서 KEY와 YM을 따로 읽어서 UNION 을 하게되면
     두개의 KEY를 기준으로 UNIQUE한 DATA가 나온다.

     SELECT YM,KEY1 FROM TEST31
     UNION
     SELECT YM,KEY1 FROM TEST32
     UNION
     SELECT YM,KEY1 FROM TEST33


     YM     KEY1
     ------ --
     199905 A
     199905 B
     199906 A
     199906 B
     199906 C
     199907 A
     199907 B
     199907 D
     199907 E
     199907 G
     199908 C
     199908 D
     199908 E
     199908 F
     199908 H

     여기까지 했으면 다했다.
     이제 위의 DATASET을 기준으로 OUTER JOIN만 해 주면 된다.

     SELECT A.YM,A.KEY1,B.AMT,C.AMT1,D.AMT2,E.AMT3
     FROM (SELECT YM,KEY1 FROM TEST31
           UNION
           SELECT YM,KEY1 FROM TEST32
           UNION
           SELECT YM,KEY1 FROM TEST33) A,
           TEST30 B,
           TEST31 C,
           TEST32 D,
           TEST33 E
     WHERE B.KEY1(+) = A.KEY1
     AND   C.KEY1(+) = A.KEY1
     AND   C.YM(+)   = A.YM
     AND   D.KEY1(+) = A.KEY1
     AND   D.YM(+)   = A.YM
     AND   E.KEY1(+) = A.KEY1
     AND   E.YM(+)   = A.YM

     결과는 문제의 답과 같다.

     PLAN :

     SELECT STATEMENT Optimizer=CHOOSE
       NESTED LOOPS (OUTER)
         NESTED LOOPS (OUTER)
           NESTED LOOPS (OUTER)
             NESTED LOOPS (OUTER)
               VIEW
                 SORT (UNIQUE)
                   UNION-ALL
                     TABLE ACCESS (FULL) OF TEST31
                     TABLE ACCESS (FULL) OF TEST32
                     TABLE ACCESS (FULL) OF TEST33
               TABLE ACCESS (BY INDEX ROWID) OF TEST33
                 INDEX (RANGE SCAN) OF TEST33_I (NON-UNIQUE)
             TABLE ACCESS (BY INDEX ROWID) OF TEST32
               INDEX (RANGE SCAN) OF TEST32_I (NON-UNIQUE)
           TABLE ACCESS (BY INDEX ROWID) OF TEST31
             INDEX (RANGE SCAN) OF TEST31_I (NON-UNIQUE)
         TABLE ACCESS (BY INDEX ROWID) OF TEST30
           INDEX (RANGE SCAN) OF TEST30_I (NON-UNIQUE)

뒷풀이.
     이번 주제는 거의 복습하는 기분으로 부담없이 들여다 봐도
     좋을 듯하다.

위로