메뉴 건너뛰기

tnt_db

Oracle 바로이전 ROW의 값을 참조하고자 할때

운영자 2002.09.18 14:31 조회 수 : 8619 추천:29

CREATE TABLE TEST02 (일자 VARCHAR2(10) PRIMARY KEY,금액 NUMBER,환율 NUMBER);
INSERT INTO TEST02 VALUES ('19980901',11500,  1350);
INSERT INTO TEST02 VALUES ('19980902',12300,  1330);
INSERT INTO TEST02 VALUES ('19980903',10900,  1390);
INSERT INTO TEST02 VALUES ('19980904',13200,  1310);
INSERT INTO TEST02 VALUES ('19980905',10800,  1350);
INSERT INTO TEST02 VALUES ('19980907',11100,  1360);
INSERT INTO TEST02 VALUES ('19980908',10600,  1340);
INSERT INTO TEST02 VALUES ('19980909',11900,  1300);
INSERT INTO TEST02 VALUES ('19980910',12000,  1290);

바로 이전 Record의 값을 참조하고자 할때.

조건.
    우리가 Query문을 작성하다보면 심심치않게 직면하는 문제다.
    뒤에 읽혀오는 Record에서 전번 Record 의 Field 값을 참조해야 하는경우
    에 대해 알아본다.

        일자   금액   환율
    -------- ------  -----
    19980901  11500   1350              
    19980902  12300   1330              
    19980903  10900   1390              
    19980904  13200   1310              
    19980905  10800   1350              
    19980907  11100   1360              
    19980908  10600   1360              
    19980909  11900   1340              
    19980910  12000   1300              
           .      .       .
           .      .       .
           .      .       .

    위와 같은 DATA를 가진 TEST02 라는 TABLE이 있다.

문제.
    현재일자 금액에 전일환율을 곱한 환산금액을 구하고 싶다.
    일주일에 한번 일요일은 금액과 환율이 안들어 오므로
    월요일에는 토요일 환율을 이용한다.

    답이 다음과 같은 계산에 의해 나오면된다.

        일자   금액        일자   환율
    -------- ------    -------- ------
    19980901  11500    
    19980902  12300    19980901   1350
    19980903  10900    19980902   1330
    19980904  13200    19980903   1390
    19980905  10800    19980904   1310
    19980907  11100    19980905   1350
    19980908  10600    19980907   1360
    19980909  11900    19980908   1340
    19980910  12000    19980909   1300
            .        .            .        .
            .        .            .        .
            .        .            .        .
            .        .            .        .

    결과는 19980904 부터 19980909 까지만 필요하다.
    최종결과가 다음과 같으면 된다.

    일자       금액       환율       환산금액  
    ---------- ---------- ---------- ----------
    19980904        13200       1390   18348000
    19980905        10800       1310   14148000
    19980907        11100       1350   14985000
    19980908        10600       1360   14416000
    19980909        11900       1340   15946000

생각.
    생각해보고 시작하자.
    어찌되었든 전번 RECORD를 읽어와야 하는데 방법을 찾아야겠다.
    엿보기1.
           앞에서 다루었듯이 자기 TABLE 과 JOIN을 걸어야 한다.
    엿보기2.
           앞에서 다루었던 자기 TABLE JOIN과 차이가 있다면
           KEY 값이 같다거나 또는 작거나같은 조건이아니라는 것이다.
           엄밀히 말하면 EQUAL JOIN 인데
           나보다 작은놈중  가장큰놈을 나와 같다라고 연결해 줄
           새로운 KEY값이 하나 필요하다.
    엿보기3.
           여기서도 ROWNUM을 이용하면 되지 않을까?..

해법.
    단계1.엿보기 내용을 그대로 실천해보자.
          일자와금액 일자와환율을 가져오는데  ROWNUM을 함께 가져오자.

          SELECT  ROWNUM,일자,금액
          FROM    TEST02 TEMP01
          WHERE   일자 BETWEEN '19980903' AND '19980909'

          과
          SELECT  ROWNUM,일자,환율
          FROM    TEST02 TEMP02
          WHERE   일자 BETWEEN '19980903' AND '19980909'
  
          4일부터의 값이 필요하지만 3일부터 가져온것은 환율때문이다.
          4일의 금액에 적용되는 환율은 3일자 환율이기 때문이다.
          실제로 4일부터라는 일자가 주어졌을때 바로전 일자를 찾아내는
          부분을 QUERY안에 포함시킬 수 도 있다.
          하지만 주제상 그부분은 생략하고 설명하기로 하겠다.

    단계2.일자는 일요일이 빠져 연속적으로 값이 일정하게 증가하지 않지만
          ROWNUM은 연속적인 값이다.
          만일 일자가 이빨이 빠지지않는 연속적인 값이었다면 ROWNUM이
          필요하지 않다. 바로 연결이 가능하기 때문이다.
          이제 나보다 작은놈중  가장큰놈을 나와 같다라고 연결해 줄
          새로운 KEY값을 만들었다.
          연결하자.
  
          SELECT TEMP01.일자,TEMP01.금액,TEMP02.환율,
                 TEMP01.금액 * TEMP02.환율 환산금액
          FROM (SELECT  ROWNUM MAIN_CNT,일자,금액
                FROM    TEST02
                WHERE   일자 BETWEEN '19980903' AND '19980909'
               )  TEMP01,
               (SELECT  ROWNUM SUB_CNT,일자,환율
                FROM    TEST02
                WHERE   일자 BETWEEN '19980903' AND '19980909'
               )  TEMP02
          WHERE  TEMP02.SUB_CNT = TEMP01.MAIN_CNT - 1

          일자       금액       환율       환산금액  
          ---------- ---------- ---------- ----------
          19980904        13200       1390   18348000
          19980905        10800       1310   14148000
          19980907        11100       1350   14985000
          19980908        10600       1360   14416000
          19980909        11900       1340   15946000
          5 행이 선택되었습니다
          구문 분석        0.01 (경과됨)      0.00 (CPU)
          실행/인출         0.06 (경과됨)      0.00 (CPU)
          합계              0.07               0.00
PLAN  
Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE
   1    0   MERGE JOIN
   2    1     SORT (JOIN)
   3    2       VIEW
   4    3         COUNT
   5    4           TABLE ACCESS (BY ROWID) OF 'TEST02'
   6    5             INDEX (RANGE SCAN) OF 'SYS_C00373' (UNIQUE)
   7    1     SORT (JOIN)
   8    7       VIEW
   9    8         COUNT
  10    9           TABLE ACCESS (BY ROWID) OF 'TEST02'
  11   10             INDEX (RANGE SCAN) OF 'SYS_C00373' (UNIQUE)


뒷풀이.
     답이 나왔다.
     이렇게 전번 ROW값을 참조하는 방법을 이용해
     누계 COLUMN이 없는 TABLE에 누계 값을 보자 (부등호 JOIN )
     에서의 문제를 다른각도로 해결하는 과정을 다음 주제에서 다뤄볼 것이다.
     확실한 이해가 있었기를.....
위로