CREATE TABLE TEST01 (A VARCHAR2(10) PRIMARY KEY, B NUMBER);
DECLARE
PL_CNT NUMBER;
BEGIN
PL_CNT :=0;
LOOP
PL_CNT := PL_CNT + 1;
EXIT WHEN PL_CNT > 1000;
INSERT INTO TEST01 VALUES
(LPAD(TO_CHAR(PL_CNT),5,'0'),PL_CNT);
END LOOP;
END;
누계 COLUMN이 없는 TABLE에 누계 값을 보자 (부등호 JOIN )
조건.
코드 값
---- ----
0001 1
0002 2
0003 3
0004 4
0005 5
0006 6
0007 7
0008 8
0009 9
0010 10
. .
. .
. .
. .
와 같은 DATA가 TEST01 이라는 TABLE에 존재한다.
편의상 코드의 COLUMN 명은 A 값의 COLUMN명은 B 라 하자.
특정 KEY값을 기준으로 (날자,숫자 등등) 값(NUMBER 타입)을 가진
COLUMN의 COLUMN 값과 함께 그 상위값들의 누계값을 보고자 하는 경우가 있다.
부등호 JOIN의 좋은 예라고 할 수 있다.
문제 .
다음과 같이 누계도 함께 보고자 하는 것이다.
코드 값 누계값
---- ---- ------
0001 1 1
0002 2 3
0003 3 6
0004 4 10
0005 5 15
0006 6 21
0007 7 28
0008 8 36
0009 9 45
0010 10 55
. . .
. . .
. . .
. . .
생각 .
어떻게 해결해야할지 잠시 생각을 해보고 엿보기를 보자.
방법이 떠오르면 그대로 해보고 비교해보는 것도 좋을 것이다.
여기서 제시되는 방법이 항상 최적은 아니다.
단지 한가지 방법에 불과할 뿐이다.
엿보기1.
각 RECORD 마다 자기보다 KEY값이 작거나 같은 값을 모두 골라서
SUM을 해주면된다.
엿보기2.
자기TABLE의 값을 참조해야하므로 자기 TABLE과 JOIN을 해야할까?
엿보기3.
JOIN은 부등호로도 이루어질 수 있다.
해법 .
단계1.엿보기 내용을 그대로 실천하면된다.
먼저 누계없는 값을 읽어오면 다음과 같다.
SELECT T01.A,
T01.B
FROM TEST01 T01
WHERE T01.A > ' '
A COLUMN에 INDEX가 있다면 A값의 순서대로 SORT되서 나올것이고
그렇지 않다고 해도 문제될것은 없으므로 WHERE절은 없어도 좋다.
PLAN 상의 차이는 있을 것이다.
즉,범위를 주어주고 해당 범위의 DATA만을 다룬다면 위의 조건이
있어야만 INDEX SCAN을 하게된다.
뒤에서 자세히 살펴보기로 하고 우선 원하는 결과를 얻는방법을
생각해 보자.
SELECT T02.A,
T02.B
FROM TEST01 T02
WHERE T02.A > ' '
같은값이 다른 ALIAS를 가지고 읽혀져왔다.
둘중에 하나를 다른쪽보다 작거나같다라는 조건으로 JOIN을
걸어서 SUM 해주면 답이다.
단계2.이렇게....
SELECT T01.A,
T01.B,
SUM(T02.B)
FROM TEST01 T01,
TEST01 T02
WHERE T02.A <= T01.A
GROUP BY
T01.A,T01.B
PLAN
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 SORT (GROUP BY)
2 1 NESTED LOOPS
3 2 TABLE ACCESS (FULL) OF 'TEST01'
4 2 TABLE ACCESS (BY ROWID) OF 'TEST01'
5 4 INDEX (RANGE SCAN) OF 'SYS_C00384' (UNIQUE)
Statistics
----------------------------------------------------------
0 recursive calls
2 db block gets
1003009 consistent gets
0 physical reads
0 redo size
25782 bytes sent via SQL*Net to client
1215 bytes received via SQL*Net from client
69 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
1000 rows processed
뒷풀이 .
문제가 있다면 RECORD수가 늘어날수록 처리시간이 지수곡선을 그리며
증가한다는 것이다.
잠간만 생각해봐도 쉽게 원인을 알 수 있다.
0001 은 자기 보다 작거나같은값이 하나
0002 는 2개 0003은 3개 0004는 4개의 RECORD와 JOIN이 이루어지면
0010 까지만 55개의 RECORD가 필요하게된다.
이런식으로 증가해서 10000건만되어도 50005000(5천5백만)건의 RECORD가
JOIN으로 인해 생성되어 처리된다.
결국 RESPONSE TIME을 고려한다면 조회의 경우
백단위내 에서만 효과가 있다는 얘기다.
벙위를 주어주고 해당범위 안의 값을 이용해 DATA가 처리된다면
효율적일 수 있다.
예를들어 값이 100 에서 199 까지 인것만을 처리하고자 한다면
다음과 같이 할 수 있을 것이다.
SELECT T01.A,
T01.B,
SUM(T02.B)
FROM TEST01 T01,
TEST01 T02
WHERE T01.A BETWEEN '00100' AND '00199'
AND T02.A BETWEEN '00100' AND '00199'
AND T02.A <= T01.A
GROUP BY
T01.A,T01.B
PLAN
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 SORT (GROUP BY)
2 1 NESTED LOOPS
3 2 TABLE ACCESS (BY ROWID) OF 'TEST01'
4 3 INDEX (RANGE SCAN) OF 'SYS_C00384' (UNIQUE)
5 2 TABLE ACCESS (BY ROWID) OF 'TEST01'
6 5 INDEX (RANGE SCAN) OF 'SYS_C00384' (UNIQUE)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
10584 consistent gets
0 physical reads
0 redo size
2708 bytes sent via SQL*Net to client
613 bytes received via SQL*Net from client
9 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
100 rows processed
1000건과 100건의 실행시간을 비교해 보면 다음과 같다.
1000 행이 선택되었습니다
구문 분석 0.00 (경과됨) 0.00 (CPU)
실행/인출 16.80 (경과됨) 0.00 (CPU)
합계 16.80 0.00
100 행이 선택되었습니다
구문 분석 0.00 (경과됨) 0.00 (CPU)
실행/인출 0.38 (경과됨) 0.00 (CPU)
합계 0.38 0.00
결과 DATA의 ROW수는 10배이지만 실행시간은 단순한 10배가 아니라는
것을 눈으로 확인할 수 있다.
참고로 다른방법이지만 같은문제를 해결하는 방법을 소개하면
이해를 도울수 있을지 모르겠다.
동일한 문제를 다음주제에서는 다른방법이지만 같은 흐름으로
해결해보도록하자.
그러기 위해서 먼저 이해하고 넘어야 할 부분을 다루도록하겠다.
DECLARE
PL_CNT NUMBER;
BEGIN
PL_CNT :=0;
LOOP
PL_CNT := PL_CNT + 1;
EXIT WHEN PL_CNT > 1000;
INSERT INTO TEST01 VALUES
(LPAD(TO_CHAR(PL_CNT),5,'0'),PL_CNT);
END LOOP;
END;
누계 COLUMN이 없는 TABLE에 누계 값을 보자 (부등호 JOIN )
조건.
코드 값
---- ----
0001 1
0002 2
0003 3
0004 4
0005 5
0006 6
0007 7
0008 8
0009 9
0010 10
. .
. .
. .
. .
와 같은 DATA가 TEST01 이라는 TABLE에 존재한다.
편의상 코드의 COLUMN 명은 A 값의 COLUMN명은 B 라 하자.
특정 KEY값을 기준으로 (날자,숫자 등등) 값(NUMBER 타입)을 가진
COLUMN의 COLUMN 값과 함께 그 상위값들의 누계값을 보고자 하는 경우가 있다.
부등호 JOIN의 좋은 예라고 할 수 있다.
문제 .
다음과 같이 누계도 함께 보고자 하는 것이다.
코드 값 누계값
---- ---- ------
0001 1 1
0002 2 3
0003 3 6
0004 4 10
0005 5 15
0006 6 21
0007 7 28
0008 8 36
0009 9 45
0010 10 55
. . .
. . .
. . .
. . .
생각 .
어떻게 해결해야할지 잠시 생각을 해보고 엿보기를 보자.
방법이 떠오르면 그대로 해보고 비교해보는 것도 좋을 것이다.
여기서 제시되는 방법이 항상 최적은 아니다.
단지 한가지 방법에 불과할 뿐이다.
엿보기1.
각 RECORD 마다 자기보다 KEY값이 작거나 같은 값을 모두 골라서
SUM을 해주면된다.
엿보기2.
자기TABLE의 값을 참조해야하므로 자기 TABLE과 JOIN을 해야할까?
엿보기3.
JOIN은 부등호로도 이루어질 수 있다.
해법 .
단계1.엿보기 내용을 그대로 실천하면된다.
먼저 누계없는 값을 읽어오면 다음과 같다.
SELECT T01.A,
T01.B
FROM TEST01 T01
WHERE T01.A > ' '
A COLUMN에 INDEX가 있다면 A값의 순서대로 SORT되서 나올것이고
그렇지 않다고 해도 문제될것은 없으므로 WHERE절은 없어도 좋다.
PLAN 상의 차이는 있을 것이다.
즉,범위를 주어주고 해당 범위의 DATA만을 다룬다면 위의 조건이
있어야만 INDEX SCAN을 하게된다.
뒤에서 자세히 살펴보기로 하고 우선 원하는 결과를 얻는방법을
생각해 보자.
SELECT T02.A,
T02.B
FROM TEST01 T02
WHERE T02.A > ' '
같은값이 다른 ALIAS를 가지고 읽혀져왔다.
둘중에 하나를 다른쪽보다 작거나같다라는 조건으로 JOIN을
걸어서 SUM 해주면 답이다.
단계2.이렇게....
SELECT T01.A,
T01.B,
SUM(T02.B)
FROM TEST01 T01,
TEST01 T02
WHERE T02.A <= T01.A
GROUP BY
T01.A,T01.B
PLAN
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 SORT (GROUP BY)
2 1 NESTED LOOPS
3 2 TABLE ACCESS (FULL) OF 'TEST01'
4 2 TABLE ACCESS (BY ROWID) OF 'TEST01'
5 4 INDEX (RANGE SCAN) OF 'SYS_C00384' (UNIQUE)
Statistics
----------------------------------------------------------
0 recursive calls
2 db block gets
1003009 consistent gets
0 physical reads
0 redo size
25782 bytes sent via SQL*Net to client
1215 bytes received via SQL*Net from client
69 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
1000 rows processed
뒷풀이 .
문제가 있다면 RECORD수가 늘어날수록 처리시간이 지수곡선을 그리며
증가한다는 것이다.
잠간만 생각해봐도 쉽게 원인을 알 수 있다.
0001 은 자기 보다 작거나같은값이 하나
0002 는 2개 0003은 3개 0004는 4개의 RECORD와 JOIN이 이루어지면
0010 까지만 55개의 RECORD가 필요하게된다.
이런식으로 증가해서 10000건만되어도 50005000(5천5백만)건의 RECORD가
JOIN으로 인해 생성되어 처리된다.
결국 RESPONSE TIME을 고려한다면 조회의 경우
백단위내 에서만 효과가 있다는 얘기다.
벙위를 주어주고 해당범위 안의 값을 이용해 DATA가 처리된다면
효율적일 수 있다.
예를들어 값이 100 에서 199 까지 인것만을 처리하고자 한다면
다음과 같이 할 수 있을 것이다.
SELECT T01.A,
T01.B,
SUM(T02.B)
FROM TEST01 T01,
TEST01 T02
WHERE T01.A BETWEEN '00100' AND '00199'
AND T02.A BETWEEN '00100' AND '00199'
AND T02.A <= T01.A
GROUP BY
T01.A,T01.B
PLAN
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 SORT (GROUP BY)
2 1 NESTED LOOPS
3 2 TABLE ACCESS (BY ROWID) OF 'TEST01'
4 3 INDEX (RANGE SCAN) OF 'SYS_C00384' (UNIQUE)
5 2 TABLE ACCESS (BY ROWID) OF 'TEST01'
6 5 INDEX (RANGE SCAN) OF 'SYS_C00384' (UNIQUE)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
10584 consistent gets
0 physical reads
0 redo size
2708 bytes sent via SQL*Net to client
613 bytes received via SQL*Net from client
9 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
100 rows processed
1000건과 100건의 실행시간을 비교해 보면 다음과 같다.
1000 행이 선택되었습니다
구문 분석 0.00 (경과됨) 0.00 (CPU)
실행/인출 16.80 (경과됨) 0.00 (CPU)
합계 16.80 0.00
100 행이 선택되었습니다
구문 분석 0.00 (경과됨) 0.00 (CPU)
실행/인출 0.38 (경과됨) 0.00 (CPU)
합계 0.38 0.00
결과 DATA의 ROW수는 10배이지만 실행시간은 단순한 10배가 아니라는
것을 눈으로 확인할 수 있다.
참고로 다른방법이지만 같은문제를 해결하는 방법을 소개하면
이해를 도울수 있을지 모르겠다.
동일한 문제를 다음주제에서는 다른방법이지만 같은 흐름으로
해결해보도록하자.
그러기 위해서 먼저 이해하고 넘어야 할 부분을 다루도록하겠다.
댓글 0
번호 | 제목 | 글쓴이 | 날짜 | 조회 수 |
---|---|---|---|---|
86 | 중복 data를 찾아 한번만 display하는 방법 | 운영자 | 2002.11.23 | 3428 |
85 | 중복 data를 찾아 모두 display 하는 방법 | 운영자 | 2002.11.23 | 3070 |
84 | oracle의 procedure에서의 여러 리턴값의 활용 예 | 운영자 | 2002.10.18 | 8301 |
83 | 특정문자까지의 왼쪽 문자열 반환 function | 운영자 | 2002.10.18 | 4044 |
82 | 중복자료 확인 및 삭제 | 운영자 | 2002.09.25 | 3259 |
81 | RECORD단위 DATA를 COLUMN단위로 | 운영자 | 2002.09.18 | 3681 |
» | 누계 COLUMN이 없는 TABLE에 누계 값을 보자 (부등호 JOIN) | 운영자 | 2002.09.18 | 5104 |
79 | 바로이전 ROW의 값을 참조하고자 할때 | 운영자 | 2002.09.18 | 8619 |
78 | 누계 COLUMN이 없는 TABLE에 누계 값을 보자 (IN-LINE VIEW) | 운영자 | 2002.09.18 | 3123 |
77 | 자기보다 작은값중 최대값 하나만 읽어오기 | 운영자 | 2002.09.18 | 4588 |
76 | DATA COPY를 이용한 QUERY | 운영자 | 2002.09.18 | 3186 |
75 | PARAMETER값 변경에따른 유연한 GROUP BY | 운영자 | 2002.09.18 | 4127 |
74 | PAIRWISE 와 NONPAIRWISE | 운영자 | 2002.09.18 | 2697 |
73 | 동일한 값 안보여주기 | 운영자 | 2002.09.18 | 2969 |
72 | 소계/합계 함께 보기 | 운영자 | 2002.09.18 | 3134 |
71 | 석차구하기 | 운영자 | 2002.09.18 | 2960 |
70 | COLUMN을 ROW로 | 운영자 | 2002.09.18 | 6135 |
69 | 최대값과 최소값을 뺀 평균 | 운영자 | 2002.09.18 | 4177 |
68 | 누계를 구하는 또한가지 방법 | 운영자 | 2002.09.18 | 3209 |
67 | 그룹 단위별 일련번호 붙이기 | 운영자 | 2002.09.18 | 5754 |