메뉴 건너뛰기

tnt_db

Oracle 한줄에 2 ROW 보여주기 변형II

운영자 2002.09.18 14:02 조회 수 : 3109 추천:15

CREATE TABLE TEST28 (항목 VARCHAR2(30), 제품 VARCHAR2(05),금액 NUMBER);
CREATE INDEX TEST28_I ON TEST28(항목);
INSERT INTO TEST28 VALUES ('매출액','A',232 );
INSERT INTO TEST28 VALUES ('매출원가','A',654);
INSERT INTO TEST28 VALUES ('매출총이익','A',646);
INSERT INTO TEST28 VALUES ('영업외손익','A',875);
INSERT INTO TEST28 VALUES ('경상이익','A',116);
INSERT INTO TEST28 VALUES ('판매물량','A',645);
INSERT INTO TEST28 VALUES ('순생산량','A',135);
INSERT INTO TEST28 VALUES ('제조원가','A',345);
INSERT INTO TEST28 VALUES ('판매단가','A',456);
INSERT INTO TEST28 VALUES ('제조단가','A',324);
INSERT INTO TEST28 VALUES ('영업단가','A',456);
INSERT INTO TEST28 VALUES ('영업외단가','A',465);
INSERT INTO TEST28 VALUES ('단위당총원가','A',654);
INSERT INTO TEST28 VALUES ('단위당이익','A',981);
INSERT INTO TEST28 VALUES ('현금단가','A',159);
INSERT INTO TEST28 VALUES ('변동단가','A',275);
--
INSERT INTO TEST28 VALUES ('매출액','B',951);
INSERT INTO TEST28 VALUES ('매출원가','B',357);
INSERT INTO TEST28 VALUES ('매출총이익','B',327);
INSERT INTO TEST28 VALUES ('영업외손익','B',852);
INSERT INTO TEST28 VALUES ('경상이익','B',249);
INSERT INTO TEST28 VALUES ('판매물량','B',248);
INSERT INTO TEST28 VALUES ('순생산량','B',893);
INSERT INTO TEST28 VALUES ('제조원가','B',954);
INSERT INTO TEST28 VALUES ('판매단가','B',354);
INSERT INTO TEST28 VALUES ('제조단가','B',753);
INSERT INTO TEST28 VALUES ('영업단가','B',462);
INSERT INTO TEST28 VALUES ('영업외단가','B',951);
INSERT INTO TEST28 VALUES ('단위당총원가','B',354);
INSERT INTO TEST28 VALUES ('단위당이익','B',456);
INSERT INTO TEST28 VALUES ('현금단가','B',654);
INSERT INTO TEST28 VALUES ('변동단가','B',321);
--
INSERT INTO TEST28 VALUES ('매출액','C',456);
INSERT INTO TEST28 VALUES ('매출원가','C',123);
INSERT INTO TEST28 VALUES ('매출총이익','C',798);
INSERT INTO TEST28 VALUES ('영업외손익','C',951);
INSERT INTO TEST28 VALUES ('경상이익','C',126);
INSERT INTO TEST28 VALUES ('판매물량','C',173);
INSERT INTO TEST28 VALUES ('순생산량','C',584);
INSERT INTO TEST28 VALUES ('제조원가','C',324);
INSERT INTO TEST28 VALUES ('판매단가','C',456);
INSERT INTO TEST28 VALUES ('제조단가','C',482);
INSERT INTO TEST28 VALUES ('영업단가','C',345);
INSERT INTO TEST28 VALUES ('영업외단가','C',732);
INSERT INTO TEST28 VALUES ('단위당총원가','C',159);
INSERT INTO TEST28 VALUES ('단위당이익','C',354);
INSERT INTO TEST28 VALUES ('현금단가','C',404);
INSERT INTO TEST28 VALUES ('변동단가','C',156);
--
INSERT INTO TEST28 VALUES ('매출액','D',156);
INSERT INTO TEST28 VALUES ('매출원가','D',354);
INSERT INTO TEST28 VALUES ('매출총이익','D',732);
INSERT INTO TEST28 VALUES ('영업외손익','D',159);
INSERT INTO TEST28 VALUES ('경상이익','D',456);
INSERT INTO TEST28 VALUES ('판매물량','D',466);
INSERT INTO TEST28 VALUES ('순생산량','D',156);
INSERT INTO TEST28 VALUES ('제조원가','D',166);
INSERT INTO TEST28 VALUES ('판매단가','D',664);
INSERT INTO TEST28 VALUES ('제조단가','D',735);
INSERT INTO TEST28 VALUES ('영업단가','D',156);
INSERT INTO TEST28 VALUES ('영업외단가','D',554);
INSERT INTO TEST28 VALUES ('단위당총원가','D',456);
INSERT INTO TEST28 VALUES ('단위당이익','D',126);
INSERT INTO TEST28 VALUES ('현금단가','D',165);
INSERT INTO TEST28 VALUES ('변동단가','D',656);
--
CREATE TABLE TEST29 (SER NUMBER,항목 VARCHAR2(30));
CREATE INDEX TEST29_I ON TEST29(SER,항목);
INSERT INTO TEST29 VALUES (1,'매출액');
INSERT INTO TEST29 VALUES (2,'매출원가');
INSERT INTO TEST29 VALUES (3,'매출총이익');
INSERT INTO TEST29 VALUES (4,'영업외손익');
INSERT INTO TEST29 VALUES (5,'경상이익');
INSERT INTO TEST29 VALUES (6,'판매물량');
INSERT INTO TEST29 VALUES (7,'순생산량');
INSERT INTO TEST29 VALUES (8,'제조원가');
INSERT INTO TEST29 VALUES (9,'판매단가');
INSERT INTO TEST29 VALUES (10,'제조단가');
INSERT INTO TEST29 VALUES (11,'영업단가');
INSERT INTO TEST29 VALUES (12,'영업외단가');
INSERT INTO TEST29 VALUES (13,'단위당총원가');
INSERT INTO TEST29 VALUES (14,'단위당이익');
INSERT INTO TEST29 VALUES (15,'현금단가');
INSERT INTO TEST29 VALUES (16,'변동단가');

"한줄에 두 ROW보여주기"  변형2
조건.
    TEST28                      TEST29

    열 이름  유형               열 이름  유형
    -------  ----               -------  ----
    항목     VARCHAR2(30)       SER      NUMBER
    제품     VARCHAR2(5)        항목     VARCHAR2(30)
    금액     NUMBER

    TEST28

    항목                           제품  금액      
    ------------------------------ ----- ----------
    매출액                         A            232
    매출원가                       A            654
    매출총이익                     A            646
    중략....
    변동단가                       A            275
    매출액                         B            951
    매출원가                       B            357
    매출총이익                     B            327
    생략...

    TEST29

    SER        항목                          
    ---------- ------------------------------
             1 매출액                        
             2 매출원가                      
             3 매출총이익                    
             4 영업외손익                    
             5 경상이익                      
             6 판매물량                      
             7 순생산량                      
             8 제조원가                      
             9 판매단가                      
            10 제조단가                      
            11 영업단가                      
            12 영업외단가                    
            13 단위당총원가                  
            14 단위당이익                    
            15 현금단가                      
            16 변동단가                      

문제.
    TEST29에 있는 순서대로 항목을 ROW로 삼고
    몇 종류가 있을지 모르는 제품을 COLUMN으로 삼아
    한번에 두제품씩 보여준다.
    제품이 두개 단위씩 바뀌면 다음에 똑같은 식으로 보여준다.
    말이 참 어렵군요..
    결과가 이렇게 나오면 된다.

    항목                           제품  금액       제품  금액      
    ------------------------------ ----- ---------- ----- ----------
    매출액                         A            232 B            951
    매출원가                       A            654 B            357
    매출총이익                     A            646 B            327
    영업외손익                     A            875 B            852
    경상이익                       A            116 B            249
    판매물량                       A            645 B            248
    순생산량                       A            135 B            893
    제조원가                       A            345 B            954
    판매단가                       A            456 B            354
    제조단가                       A            324 B            753
    영업단가                       A            456 B            462
    영업외단가                     A            465 B            951
    단위당총원가                   A            654 B            354
    단위당이익                     A            981 B            456
    현금단가                       A            159 B            654
    변동단가                       A            275 B            321

    매출액                         C            456 D            156
    매출원가                       C            123 D            354
    매출총이익                     C            798 D            732
    영업외손익                     C            951 D            159
    경상이익                       C            126 D            456
    판매물량                       C            173 D            466
    순생산량                       C            584 D            156
    제조원가                       C            324 D            166
    판매단가                       C            456 D            664
    제조단가                       C            482 D            735
    영업단가                       C            345 D            156
    영업외단가                     C            732 D            554
    단위당총원가                   C            159 D            456
    단위당이익                     C            354 D            126
    현금단가                       C            404 D            165
    변동단가                       C            156 D            656

생각.
    이왕 시작한 것이니 ROWNUM을 이용하는 방법에 대해서 정통하자.




            보통의 SYSTEM에서는 제품이 들어가면 그 제품을 관리하는
            TABLE이 따로 있겠지만 이번 예제에서는 제품을 따로
            관리하는 TABLE이 없다고 가정한다.
            예를 제품으로 들었을 뿐이지 제품이 아닌 그 어떤것도 해당될
            수 있기 때문이다.
            결국 TEST28에 존재하는 제품을 우선 추려내야 한다는 결론이
            나온다.
            제품을 관리하는 TABLE이 있다해도 TEST28에 존재하는 제품을
            추려내는 과정은 거쳐야 한다.
    엿보기2.이렇게 제품을 추려내면 TABLE에 존재하는 유일한 제품에
            대해서 번호를 부여할 수 있을 것이다.    
            제품의 첫번째와 두번째는 처음 PAGE에 세번째와 네번째는
            다음 PAGE에 보여주기로 했기 때문에, 그 제품이 몇번째
            제품에 해당하는지를 알아야 하기 때문이다.
    엿보기3.그렇게 추려낸 제품을 TEST28의 제품과 연결해 주면
            동일한 제품에는 모두 동일한 번호가 붙을 것이다.
            그 번호를 이용해서 1번,2번 제품에는 1이라는 번호를 매겨주고
            3번,4번은 2를 5번,6번은 3이라는 번호를 매겨줄 수 있을 것이다.
            이미 앞의 문제에서 여러번 경험 했기 때문에 어렵지
            않을 것이다.
            그렇게 하면 이제품이 몇번째 PAGE에 나와야 하는지를
            결정할 수 있다.
    엿보기4.여기까지 정리가 되었으면 어려운것은 모두 끝났다고 봐도
            좋으리라.
            다음으로 할 일은 결정된 PAGE내에서 항목순으로
            정렬을 하고,
            1,2/3,4/5,6/....등을 같은 GROUP BY단위로 엮어주면 된다
해법.
    단계1.제품을 UNIQUE하게 읽어서 가져와보자.

          SELECT 제품 FROM TEST28 GROUP BY 제품;

          일단은 지금 존재하고 있는 A,B,C,D 네개의 제품만 나온다.
          만약 제품관리 TABLE이 있다면 EXISTS 등을 통해 효율적으로
          존재하는 제품만 가져올 수 있을 것이다.
    단계2.읽어온 제품에 번호를 붙이자.

          SELECT ROWNUM RNUM,제품
          FROM  (SELECT 제품 FROM TEST28 GROUP BY 제품);

    단계3.2번의 DATASET을 TEST28과 연결해서 다음정보를 보자.

          SELECT A.항목,A.제품,A.금액,C.RNUM
          FROM   TEST28 A,
                (SELECT ROWNUM RNUM,제품
                 FROM  (SELECT 제품 FROM TEST28 GROUP BY 제품) ) C
          WHERE   C.제품 = A.제품
  
          항목                           제품  금액       RNUM      
          ------------------------------ ----- ---------- ----------
          매출액                         A            232          1
          매출원가                       A            654          1
          중략.............
          변동단가                       A            275          1
          매출액                         B            951          2
          매출원가                       B            357          2
          중략.............
          변동단가                       B            321          2
          매출액                         C            456          3
          매출원가                       C            123          3
          중략.............
          변동단가                       C            156          3
          매출액                         D            156          4
          매출원가                       D            354          4
          생략.............
          
          이번 역시 테이블안의 전체 데이터를 대상으로하며,
          참고 :TEST28에서 제품을 읽을때는 전체 DATA를 읽어서 찾아야
                하므로 INDEX SCAN을 하지 않았다.

    단계4.RNUM이 1,2인 제품에 1을 3,4인제품에 2를 붙여서 다시읽어보자.
          다음방법을 써보자.그리고 이름을 PAGE 라고 붙이자.

          CEIL(C.RNUM/2)          

          CEIL이란 함수는 모두 알겠지만 잠시 설명하면
          해당값보다 큰 정수중 가장작은 값을 RETURN하는 함수이다.
          그렇게 하면 2로 나눈 값 이기때문에
          1과2는 1을, 3과4는 2를, 5와6이 있다면 3을 RETURN 할 것이다.

          SELECT A.항목,A.제품,A.금액,C.RNUM,CEIL(C.RNUM/2) PAGE
          FROM   TEST28 A,
                (SELECT ROWNUM RNUM,제품
                 FROM  (SELECT 제품 FROM TEST28 GROUP BY 제품) ) C
          WHERE   C.제품 = A.제품;

          항목                제품  금액       RNUM       PAGE
          ------------------- ----- ---------- ---------- ----------
          매출액              A            232          1          1
          매출원가            A            654          1          1
          매출총이익          A            646          1          1
          중략.............
          변동단가            A            275          1          1
          매출액              B            951          2          1
          매출원가            B            357          2          1
          중략.............
          변동단가            B            321          2          1
          매출액              C            456          3          2
          매출원가            C            123          3          2
          중략.............
          현금단가            C            404          3          2
          변동단가            C            156          3          2
          매출액              D            156          4          2
          매출원가            D            354          4          2
          매출총이익          D            732          4          2
          생략.............


    단계5.마지막으로 할일은 같은 PAGE 내에서의 ROW의 순서를 결정
          해주기 위해 TEST29와 JOIN을 한 후
          PAGE 와 TEST29의 SER 로 GROUP BY 하면된다.
          이때 RNUM이 홀수인 제품과 금액을 앞에,짝수인 제품과 금액을
          뒤에 보여주기위하여 MAX(DECODE()) 또는 MIN(DECODE())를
          이용하면 된다.
          최종 결과는 아래와 같다.

          SELECT  CEIL(C.RNUM/2) PAGE,
                  B.SER          SEQ,
                  A.항목         항목,
                  MAX(DECODE(MOD(C.RNUM,2),1,A.제품)) 제품,
                  MAX(DECODE(MOD(C.RNUM,2),1,A.금액)) 금액,
                  MAX(DECODE(MOD(C.RNUM,2),0,A.제품)) 제품,
                  MAX(DECODE(MOD(C.RNUM,2),0,A.금액)) 금액
          FROM    TEST28 A,
                 (SELECT ROWNUM RNUM,제품
                  FROM  (SELECT 제품 FROM TEST28 GROUP BY 제품) ) C,
                  TEST29 B
          WHERE   B.항목 = A.항목
          AND     C.제품 = A.제품
          GROUP BY CEIL(C.RNUM/2),B.SER,A.항목

          PLAN :
      
          SELECT STATEMENT Optimizer=CHOOSE
            SORT (GROUP BY)
              MERGE JOIN
                SORT (JOIN)
                  NESTED LOOPS
                    TABLE ACCESS (FULL) OF TEST29
                    TABLE ACCESS (BY INDEX ROWID) OF TEST28
                      INDEX (RANGE SCAN) OF TEST28_I (NON-UNIQUE)
                SORT (JOIN)
                  VIEW
                    COUNT
                      VIEW
                        SORT (GROUP BY)
                          TABLE ACCESS (FULL) OF TEST28

뒷풀이.
    이런류의 결과물은 주로 출력용으로 이용된다.
    REPORT TOOL이 좋은 경우는 TOOL을 이용하면 쉽게 해결되지만
    이해해 두어 손해 볼일은 없을 것이다.
위로