메뉴 건너뛰기

tnt_db

Oracle 고정된 Row 수 유지

운영자 2002.09.18 14:06 조회 수 : 4228 추천:16

고정된 Row 수 유지

조건.
    ORACLE SCOTT USER 에 LOGIN 하면 DEPT 라는 TABLE이 있다.
    SCOTT USER의 DEPT는 다음과 같다.

    열 이름                        널?      유형
    ------------------------------ -------- ----
    DEPTNO                                  NUMBER(2)
    DNAME                                   VARCHAR2(14)
    LOC                                     VARCHAR2(13)

문제.
    질문내용:
    "select * from dept where dept_code=12
     에서 select 된 row의 갯수가 3개이면 7개 row의 값이 null 값으로
     채워지고
     select 된 row의 갯수가 4개이면 6개 row의 값이 null 값으로 채워져
     select된 row의 수는 항상 10개를 유지 합니다.
     이런 select문이 가능한지요.."

    아마 DEPT TABLE 이 SCOTT USER 에서 제공되는 TABLE 이 아닌
    직접 CREATE 시킨 TABLE인듯 하다.
    DEPT_CODE = 12 라는 조건이 들어 있는 것으로 봐서 짐 작할 수 있다.

생각.
    위의 질문을 만족하기 위해서는 항상 조건식에 의해 DEPT TABLE에서
    읽혀오는 DATA의 건수가 10개보다 작아야 의미가 있을 것이다.
    10개를 넘는다 해도 문제 될것은 없지만 10개의 RECORD로
    고정 시키다 보면  11번째 DATA부터는 결과에 포함되어 나오지 않기
    때문이다.
    어떤 양식을 맞추거나 약간의 편법을 이용해 다른 문제를 뚫고
    나가기위해 필요하지 않았는가 싶다.
    어쨋든 위의 문제에 대한 해답을 구하고 어느 경우에 쓰일 수
    있는지도 생각해 보자.
    우리가 사용할 DEPT TABLE은 조건에 나타나 있는 TABLE이다.
    결과가 아래와 같이 나오면 될듯 하다.

    DEPTNO     DNAME          LOC          
    ---------- -------------- -------------
            10 ACCOUNTING     NEW YORK    
            20 RESEARCH       DALLAS      
            30 SALES          CHICAGO      
            40 OPERATIONS     BOSTON      
                                                        
                                                        
                                                        
                                                        
                                                        
                                                        
    10 행이 선택되었습니다.
  
    DEPT TABLE에서 결과를 만족하는 DATA가 몇개이든 간에
    "10 행이 선택되었습니다." 라는 메세지가 떠야 한다.
    
해법.
    쉽게 생각하면 쉬운 문제다.
    우리는 이미 OUTER JOIN에 대하여 알고 있다.
    어떤 테이블이 있다고 가정하자.
    DEPT TABLE 과  1:1 조인을 걸수있는 TABLE 이고
    그 테이블에서는 항상 DEPT에서 추출된 결과를 포함하는 10개의 RECORD를
    RETURN 할 수 있으면 DEPT와 그 테이블을 EQUAL JOIN 으로 연결하되
    DEPT 에 OUTER 조인이 되도록 연결하면 된다.
    예를 들어 보자.

    다음과 같은 구조와 DATA를 가진 TEST27 이라는 TABLE이 있다.
    그렇다면 간단할 것이다.

        DEPTNO    
    ----------
            10
            20
            30
            40
            50
            60
            70
            80
            90
           100
    10 행이 선택되었습니다
    
    두 TABLE을 OUTER JOIN으로 연결만 하면 될테니까..
    연결해보자.

    SELECT A.DEPTNO,DNAME,LOC
    FROM   DEPT A,
           TEST27 B
    WHERE  A.DEPTNO(+) = B.DEPTNO

    DEPTNO     DNAME          LOC          
    ---------- -------------- -------------
            10 ACCOUNTING     NEW YORK    
            20 RESEARCH       DALLAS      
            30 SALES          CHICAGO      
            40 OPERATIONS     BOSTON      
                                      
                                      
                                      
                                      
                                      
                                      
    10 행이 선택되었습니다
  
    와 같은 결과가 나온다.
    그런데 몇가지 문제가 있다.
    첫번째 QUERY 하나를 위해 TABLE을 새로 만들어야 하며
    두번째 부서 TABLE에 조건이 걸리면 TEST27에도 같은 조건을
    걸어줘야하고, 그것을 포함해 10개가 될수 있도록 QUERY를
    구성해 줘야한다
    그래서 항상 TEST27에는 10개 이상의 RECORD가
    TEST27에 있는 DEPTNO를 모두 포함하면서 존재해야한다.
    이유는 DEPT TABLE에 현재처럼 DATA가 4개밖에 없으면
    DEPT 하나의 TABLE만으로는 해결이 곤란하기 때문이다.
    세번째 DEPT TABLE에 변경이 일어날때마다 TEST26 도 함께
    고려해야 한다는 것이다.
    QUERY하나를 성공시키기 위해 너무 많은 희생을 치뤄야 한다.
    세가지 문제가 발생하는 근본적인 원인은 우리가 1:1 조인의
    연결고리를 DEPTNO로 잡았기 때문이다.
    그렇다면 연결고리를 바꿀 방법은 없는가?.
    연결고리를 항상 일정하게 변하지 않는 것으로 잡는다면
    어떤 DEPTNO 가 결과에 끌려오더라도 문제가 없을듯한데...
    제일먼저 무엇이 떠오르는가?.
    문제에서 요구하는 것이 10 건의 RECORD를 유지시켜 달라는
    것이었다.
    DEPT의 1번 RECORD가 그 어떤 TABLE의 1번과 2번이 2번과
    .....10번이 있다면
    10번과 10번이 연결되고 10번을 포함한 그이하가 DEPT에 없더라도
    OUTER JOIN으로 10번과 연결하면 항상 10개의 RECORD가
    나올 것이다.
    이제 문제의 핵심이 좁혀졌다.
    DEPT 와 JOIN을 걸어줄 어떤 TABLE에서 읽혀오는 두개의 DATASET에
    번호표를 붙여주고 같은 번호끼리 연결을 해보자.
    그 어떤 TABLE은 단지 무작정 10개의 번호만 제공하면된다.
    그 이상은 필요가 없다.
    10개의 번호를 제공할 수 있는 TABLE은 10개 이상의 RECORD가
    존재하는 TABLE이면 된다.
    반드시 TABLE이 아닌 VIEW라도 좋다.
    여기서는 USER_TABLES를 이용하자.
    다음과 같은 QUERY를 만들면
    select rownum r_cnt from user_tables where rownum < 11
    아래와 같은 결과가 나오리라.

    R_CNT    
    ----------
             1
             2
             3
             4
             5
             6
             7
             8
             9
            10
    10 행이 선택되었습니다
    
    이번에는 DEPT TABLE에 번호표를 달아서 읽어보자.

    select rownum r_cnt,deptno,dname,loc from dept

    R_CNT      DEPTNO     DNAME          LOC          
    ---------- ---------- -------------- -------------
             1         10 ACCOUNTING     NEW YORK    
             2         20 RESEARCH       DALLAS      
             3         30 SALES          CHICAGO      
             4         40 OPERATIONS     BOSTON      
    이제 두 DATASET을 OUTER JOIN으로 연결하자.

    select deptno,dname,loc
    from  (select rownum r_cnt,deptno,dname,loc
           from   dept ) a,
          (select rownum r_cnt from user_tables
           where  rownum < 11) b
    where a.r_cnt(+) = b.r_cnt

    결과는 문제의 답과 동일하다.
뒷풀이.
    언제 쓰일 수있는 QUERY 인가.
    전혀 상관관계가 없는 두개의 DATASET을 1:1로 조인 하고자 할때
    유용할 것이다.
    흔히 상관없는 DATA가 JOIN이 걸리면 연결고리가 없으므로 M:N 으로
    CARTESIAN PRODDUCT가 일어나는 것이 일반 적이다.
    어떤 이유로해서 두개의 연결고리가 필요할때 유용하게 쓰일 수
    있는 방법이다.
    살며시 기억해 두자.
위로