메뉴 건너뛰기

tnt_db

Oracle RECORD단위 DATA를 COLUMN단위로

운영자 2002.09.18 14:33 조회 수 : 3507 추천: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값의
       변동에 따라 계산을 해줄 수 있다.
번호 제목 글쓴이 날짜 조회 수
86 LENGTH/LENGTHB,SUBSTR/SUBSTRB,INSTR/INSTRB 운영자 2002.09.18 4050
85 PARAMETER값 변경에따른 유연한 GROUP BY 운영자 2002.09.18 4040
84 최대값과 최소값을 뺀 평균 운영자 2002.09.18 3941
83 한번 읽은 테이블로 백분율 구하기 운영자 2002.09.18 3834
82 plan table(sql실행계획) 보는 select문 운영자 2003.01.28 3831
81 다중 Row 결과를 단일행으로 컴마로 분리해 출력하는 방법 (2) 박상현 2006.06.13 3816
80 sybase DB에서 파일로 백업을 받구 그파일을 다시 DB2로 임포트하는방법 원우석 2004.07.31 3748
79 특정문자까지의 왼쪽 문자열 반환 function 운영자 2002.10.18 3743
78 row데이터 연결하여 조회 구퍼 2009.03.31 3663
77 년중 몇번째 주간인지 알아내기(FUNCTION) - ORACLE이 제공하는 것과 다름 운영자 2002.09.17 3630
76 최단거리찾기 혹은 멀리 떨어진 두지점간의 거리의 합구하기 박상현 2006.11.07 3608
75 다수 NULL 허용 COLUMN의 명칭을 가져올때 운영자 2002.09.18 3572
74 문자열 행으로 분리하기 박상현 2006.06.13 3552
73 다중 Row 결과를 단일행으로 컴마로 분리해 출력하는 방법 (1) 박상현 2006.06.13 3537
72 복제를이용한 합계계에서 비율계산 운영자 2002.09.18 3534
» RECORD단위 DATA를 COLUMN단위로 운영자 2002.09.18 3507
70 sql 문 실행명령 원우석 2004.07.31 3500
69 최대공약수, 최소공배수 구하기 박상현 2006.06.13 3479
68 PL/SQL에서 쿼리시 Array Processing 처리방법 박상현 2006.10.27 3469
67 반올림 DATA의 오차보정 운영자 2002.09.18 3463
위로