메뉴 건너뛰기

tnt_db

Oracle RECORD단위 DATA를 COLUMN단위로

운영자 2002.09.18 14:33 조회 수 : 3681 추천:32

CREATE TABLE SAM_TAB02 (구분 VARCHAR2(5) );
DECLARE
SU NUMBER;
BEGIN
SU:=106;
LOOP
SU:=SU+1;
EXIT WHEN SU>125;
INSERT INTO SAM_TAB02
VALUES('F'||TO_CHAR(SU));
END LOOP;
END;

RECORD 단위 DATA 를 COLUMN 단위로

조건
    개발자는 고객의 요구를 자~알 만족시켜줘야한다.
    하지만 우리의 유저는 머리속에서만 구현가능하면 당연히 컴퓨터도
    할 수 있다고 생각하고 그것을 요구한다.
    그럼 어쩌나?...해줘야지..
    1. 우리가 흔히 DATA를 다룰때 RECORD 단위로 뿌려지는 DATA를
       COLUMN 단위로 보아야 할 경우가 있다.
    2. 레코드가 몇개가 나올지 모르는 DATA를  끝도없이 옆으로
       늘려간다는것도 불가능하니 주어지는 단위만큼 보여주고
       다시 다음 줄에보여주고 하는식의 QUERY를 구현하고자 한다.
    3. 쉽게 얘기해서
       SAM_TAB2 의 여러 COLUMN 중 "구분" 이라는 COLUMN 에
       다음과 같은 DATA가 들어있다.

              구분
              ----
              F106
              F107
              F108
              F109
              F110
              F111
              F112
              F113
              F114
              F115
              F116
              F117
              F118
              F119
              F120
              F121
              F122
              F123
              F124
              F125

       위와같이 QUERY 되어 나오는 DATA를

             순서   COL1   COL1   COL1    COL1
             ----   ----   ----   ----    ----
              01    F106   F107   F108    F109
              02    F110   F111   F112   F113
              03    F114   F115   F116    F117
              04    F118   F119   F120   F121
              05    F122   F123   F124   F125

       이렇게 보고싶다는 이야긴데...        

문제 .
       조건에서 문제를 얘기해버렸네..
       그래도 문제는 있어야지!.
       자~알 보여주세요.

생각 .
       문제에 부딪히면 누구나 생각을 먼저 하게 된다.
       결과가 좋은지 나쁜지는 다음문제지만..
       어쨋든 생각을 해보자
       엿보기1. 모든 QUERY 에는  ROWNUM이라는 놈이 함께 달려나온다.
                각 RECORD 마다에 번호표를 붙여줄 수 있다는 얘기다.
             2. 그럼 더이상 엿볼게 없다.
                붙여진 번호표를 각번호마다 불러서
                몇번은 몇번째줄 몇번째칸에 가서 서라....라고 명령만하면
                자기가 자기집을 찾아가서 서버리기 때문이다.
             3. 우리가 할일은 더이상 없다.

해법 .
       생각하다보니 해법이 다 나왔다.
       말만 바꿔주면된다.

       단계1. 제일먼저 각 RECORD마다 번호표를 붙여준다.
              SELECT ROWNUM CNT,TYPE_CD
              FROM   HDAT_TYPE_CD
       단계2. 위에서 읽혀온 DATASET 을 이용해 다음에 할일은
              각번호를 몇번째 ROW 몇번째 COLUMN 에 세울건지를
              결정해줘야한다.
              답이 이미 4개단위로 되어있으니 한ROW에 보여주는
              RECORD 는 4개로 결정짓자.
              결국
              1  2  3  4
              5  6  7  8
              9 10 11 12
             13 14 15 16
             17 18 19 20
              과 같은 식으로 DATA의 배열이 이루어지면된다.
              먼저 ROW를 생각하면
              4개의 RECORD가 같은 ROW번호표를 갖고
              같은 줄의 각각의 DATA가 순서대로 1번부터 4번까지를 나눠
              가지면 된다.
        
              ROW     COL     DATA
              ---     ---     ----
                1       1        1
                1       2        2
                1       3        3
                1       4        4
                2       1        5
                2       2        6
                2       3        7
                2       4        8
                3       1        9
                3       2       10
                3       3       11
                3       4       12
                4       1       13
                4       2       14
                4       3       15
                4       4       16
                5       1       17
                5       2       18
                5       3       19
                5       4       20
               즉 위와 같은식으로 되면된다.
             이렇게 써주면 된다.
            
             SELECT CEIL(CNT/4) ROW_CNT,
                    DECODE(MOD(CNT,4),0,4,MOD(CNT,4)),
                    구분
             FROM
                 (SELECT ROWNUM CNT,구분
                  FROM   SAM_TAB2
                 )

       단계3.이제 배열만 하면 된다.
             SELECT CEIL(CNT/4) ROW_CNT,
                    MAX(DECODE(MOD(CNT,4),1,구분)),
                    MAX(DECODE(MOD(CNT,4),2,구분)),
                    MAX(DECODE(MOD(CNT,4),3,구분)),
                    MAX(DECODE(MOD(CNT,4),0,구분))
             FROM
                 (SELECT ROWNUM CNT,구분
                  FROM   SAM_TAB2
                 )
            GROUP BY CEIL(CNT/4)
            이것이 답이다.
PLAN
Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE
   1    0   SORT (GROUP BY)
   2    1     VIEW
   3    2       COUNT
   4    3         TABLE ACCESS (FULL) OF 'SAM_TAB2'




뒷풀이 .
       단계3 에서 해준일은 ROW_CNT 를 Grouping 단위로 하여
       Column Count 에 따라 위치를 정해주고 그값이 존재하는
       Column만으로 Data를 압축시킨경우이다.
       우리가 흔히 사용하는 SUM(DECODE()) 와 같은 경우다.
       그래도 이해가 안되시는 분들을 위해 잠간 그림을 그려보면

       SELECT CEIL(CNT/4) ROW_CNT,
              DECODE(MOD(CNT,4),1,구분),
              DECODE(MOD(CNT,4),2,구분),
              DECODE(MOD(CNT,4),3,구분),
              DECODE(MOD(CNT,4),0,구분)
       FROM
           (SELECT ROWNUM CNT,구분
            FROM   SAM_TAB2
           )
      
       그룹지어주지 않은 자료이다.
       ROW_CNT COL1 COL2 COL3 COL4
       ------- ---- ---- ---- ----
             1 F106              
             1      F107          
             1           F108    
             1                F109
             2 F110              
             2      F111          
             2           F112    
             2                F113
             3 F114              
             3      F115          
             3           F116    
             3                F117
             4 F118              
             4      F119          
             4           F120    
             4                F121
             5 F122              
             5      F123          
             5           F124    
             5                F125
       이 자료를 ROW_CNT로 그룹지어
       각 COLUMN의 최대값을 가져오면

           순서   COL1   COL1   COL1    COL1
           ----   ----   ----   ----    ----
            01    F106   F107   F108    F109
            02    F110   F111   F112    F113
            03    F114   F115   F116    F117
            04    F118   F119   F120    F121
            05    F122   F123   F124    F125
       이렇게 답이되는 것이다.    
사족 .
       단점이라면 몇COLUMN을 한 ROW에 볼것인가 하는 문제를 미리
       결정해줘야 한다는 것이다.
       경우에 따라 한줄에 몇 COLUMN 이 올지 모르는 경우라면
       그 최대 COLUMN 수를 MAX(DECODE())로 만들어 놓고 PARAMETER값의
       변동에 따라 계산을 해줄 수 있다.
위로