메뉴 건너뛰기

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값의
       변동에 따라 계산을 해줄 수 있다.
번호 제목 글쓴이 날짜 조회 수
74 TABLE,COLUMN,PROCEDURE 이름을 확인할때... 원우석 2006.03.10 3114
73 NESTED TABLE과 VARRAY사용법과 다른점 박상현 2005.11.03 8834
72 plan table(sql실행계획) 보는 select문 운영자 2003.01.28 3988
71 java에서 array처리 방법 운영자 2003.01.27 6189
70 효율적인 25가지 SQL작성법 운영자 2003.01.04 2948
69 중복 data는 처음에만 display 하게 하는 방법 운영자 2002.11.23 2965
68 중복 data를 찾아 한번만 display하는 방법 운영자 2002.11.23 3428
67 중복 data를 찾아 모두 display 하는 방법 운영자 2002.11.23 3070
66 oracle의 procedure에서의 여러 리턴값의 활용 예 운영자 2002.10.18 8301
65 특정문자까지의 왼쪽 문자열 반환 function 운영자 2002.10.18 4044
64 중복자료 확인 및 삭제 운영자 2002.09.25 3259
» RECORD단위 DATA를 COLUMN단위로 운영자 2002.09.18 3681
62 누계 COLUMN이 없는 TABLE에 누계 값을 보자 (부등호 JOIN) 운영자 2002.09.18 5104
61 바로이전 ROW의 값을 참조하고자 할때 운영자 2002.09.18 8619
60 누계 COLUMN이 없는 TABLE에 누계 값을 보자 (IN-LINE VIEW) 운영자 2002.09.18 3123
59 자기보다 작은값중 최대값 하나만 읽어오기 운영자 2002.09.18 4588
58 DATA COPY를 이용한 QUERY 운영자 2002.09.18 3186
57 PARAMETER값 변경에따른 유연한 GROUP BY 운영자 2002.09.18 4127
56 PAIRWISE 와 NONPAIRWISE 운영자 2002.09.18 2697
55 동일한 값 안보여주기 운영자 2002.09.18 2969
위로