문제.
PARAMETER 로 FROM 월과 TO월이 주어지면 해당월 사이의 월을
모두 구해내는 문제이다.
즉 시작월로 '199906' 이 주어지고 마지막월로 '200004' 가 주어진다면
RNUM TIT
---------- ----------------
1 1999.06
2 1999.07
3 1999.08
4 1999.09
5 1999.10
6 1999.11
7 1999.12
8 2000.01
9 2000.02
10 2000.03
11 2000.04
와 같은 결과를 만들어 내는 것이다.
시작월과 마지막월 PARAMETER 대신 각각 '199906' 과 '200004'를
사용한다.
생각.
기간을 가져오기 위해 몇년분의 일자나 또는 몇년분의 월만을 따로
보관하는 경우를 흔히 볼수 있다.
단순히 조건으로 주어진 기간내의 일이나 월이 필요해서 그 값을
읽어오기 위해서다.
그것이 나쁘다는 얘기는 아니지만 그렇게 TABLE까지 만들어서
관리하지 않아도 값을 읽을 수 있는 방법을 알아보기 위해서다.
RNUM 이라는 값은 참조용이고 실제로 구하기를 원하는 값은
결과에서 나타난 TIT 값이다.
위의 결과를 가만히 살펴보면 다음과 같은 정보를 얻어낼 수
있을 것이다.
첫번째 TIT 값은 시작월로 들어온 값 그대로이고,
두번째는 1달을 더한값,
세번째는 2달을 더한값, N번째는 N-1을 더한값 이라는 것을.
가볍게 해결할 수 있는 문제이다.
문제를 푸는 핵심은 역시 ROWNUM 이다.
주어지는 기간을 ROW수로 환산했을때 그 최대값을 충분히
수용할 수 있는 만큼의 ROW를 가진 TABLE에서 ROWNUM을 읽어온다.
다음으로
읽어온 ROWNUM중 기간값에 들어가는 수만큼을 조건절에서 걸러낸다.
기간값이 2월부터 12월 이면 11개의 월이 필요하므로 ROWNUM중
1번부터 11번까지만을 읽어오는 식이다.
그렇게 한 후 시작월에 ROWNUM-1 만큼씩 월을 더해가면 된다.
이때 함수 ADD_MONTHS 를 이용한다.
해법.
단계1.
SELECT ROWNUM
FROM (SELECT ROWNUM RNUM FROM USER_TABLES)
처럼 기술하면 USER_TABLES에 있는 ROW 수 만큼의 번호를
RNUM 이라는 이름으로 가져오게 된다.
이 중에서 기간사이에 해당하는 ROW 수 만큼 제한을 두는 방법을
생각해 보자.
문제의 경우는 1에서 11까지를 가져와야 하기때문에 RNUM < 12
와 같이 조건을 주면 된다.
'200004' 와 '199906'을 이용해서 12 또는 11 이라는 값을
만들어 낼 수 있는가?.
DATE 로 형 변환한 후 월에서 월을 빼면 그 사이의
일자수가 나온다.
그값을 이용해 한달을 30일 이라고 가정하고 30 으로 나눈후
그보다 큰 정수 값을 받는 것도 한가지 방법이다.
CEIL((TO_DATE(200010,'YYYYMM') - TO_DATE(199912,'YYYYMM'))/30)
처럼
문제는 없겠지만 그 값이 의심스러우면 다음과 같은 방법을
이용해 보자.
WHERE ADD_MONTHS(TO_DATE('199906','YYYYMM'), RNUM -1 ) <=
TO_DATE('200004','YYYYMM')
위와같이 하면 확실한 값을 얻을 수 있다.
단계2.문제는 다 해결되었다.
이제 SELECT 절에 시작월 + RNUM - 1 만큼 을 읽어 오도록 기술한다.
이렇게
TO_CHAR(ADD_MONTHS(TO_DATE('199906','YYYYMM'),RNUM-1),'YYYY.MM')
최종 문장은 아래와 같다.
SELECT RNUM,
TO_CHAR(ADD_MONTHS(TO_DATE('199906','YYYYMM'),
RNUM -1 ),'YYYY.MM')
FROM (SELECT ROWNUM RNUM FROM USER_TABLES)
WHERE ADD_MONTHS(TO_DATE('199906','YYYYMM'), RNUM -1 ) <=
TO_DATE('200004','YYYYMM')
여기에서 강제로 주어진 시작값과 끝값을 PARAMETER 값으로
바꾸면 상황에 따라 유용하게 쓰일 수 있을 것이다.
PARAMETER 로 FROM 월과 TO월이 주어지면 해당월 사이의 월을
모두 구해내는 문제이다.
즉 시작월로 '199906' 이 주어지고 마지막월로 '200004' 가 주어진다면
RNUM TIT
---------- ----------------
1 1999.06
2 1999.07
3 1999.08
4 1999.09
5 1999.10
6 1999.11
7 1999.12
8 2000.01
9 2000.02
10 2000.03
11 2000.04
와 같은 결과를 만들어 내는 것이다.
시작월과 마지막월 PARAMETER 대신 각각 '199906' 과 '200004'를
사용한다.
생각.
기간을 가져오기 위해 몇년분의 일자나 또는 몇년분의 월만을 따로
보관하는 경우를 흔히 볼수 있다.
단순히 조건으로 주어진 기간내의 일이나 월이 필요해서 그 값을
읽어오기 위해서다.
그것이 나쁘다는 얘기는 아니지만 그렇게 TABLE까지 만들어서
관리하지 않아도 값을 읽을 수 있는 방법을 알아보기 위해서다.
RNUM 이라는 값은 참조용이고 실제로 구하기를 원하는 값은
결과에서 나타난 TIT 값이다.
위의 결과를 가만히 살펴보면 다음과 같은 정보를 얻어낼 수
있을 것이다.
첫번째 TIT 값은 시작월로 들어온 값 그대로이고,
두번째는 1달을 더한값,
세번째는 2달을 더한값, N번째는 N-1을 더한값 이라는 것을.
가볍게 해결할 수 있는 문제이다.
문제를 푸는 핵심은 역시 ROWNUM 이다.
주어지는 기간을 ROW수로 환산했을때 그 최대값을 충분히
수용할 수 있는 만큼의 ROW를 가진 TABLE에서 ROWNUM을 읽어온다.
다음으로
읽어온 ROWNUM중 기간값에 들어가는 수만큼을 조건절에서 걸러낸다.
기간값이 2월부터 12월 이면 11개의 월이 필요하므로 ROWNUM중
1번부터 11번까지만을 읽어오는 식이다.
그렇게 한 후 시작월에 ROWNUM-1 만큼씩 월을 더해가면 된다.
이때 함수 ADD_MONTHS 를 이용한다.
해법.
단계1.
SELECT ROWNUM
FROM (SELECT ROWNUM RNUM FROM USER_TABLES)
처럼 기술하면 USER_TABLES에 있는 ROW 수 만큼의 번호를
RNUM 이라는 이름으로 가져오게 된다.
이 중에서 기간사이에 해당하는 ROW 수 만큼 제한을 두는 방법을
생각해 보자.
문제의 경우는 1에서 11까지를 가져와야 하기때문에 RNUM < 12
와 같이 조건을 주면 된다.
'200004' 와 '199906'을 이용해서 12 또는 11 이라는 값을
만들어 낼 수 있는가?.
DATE 로 형 변환한 후 월에서 월을 빼면 그 사이의
일자수가 나온다.
그값을 이용해 한달을 30일 이라고 가정하고 30 으로 나눈후
그보다 큰 정수 값을 받는 것도 한가지 방법이다.
CEIL((TO_DATE(200010,'YYYYMM') - TO_DATE(199912,'YYYYMM'))/30)
처럼
문제는 없겠지만 그 값이 의심스러우면 다음과 같은 방법을
이용해 보자.
WHERE ADD_MONTHS(TO_DATE('199906','YYYYMM'), RNUM -1 ) <=
TO_DATE('200004','YYYYMM')
위와같이 하면 확실한 값을 얻을 수 있다.
단계2.문제는 다 해결되었다.
이제 SELECT 절에 시작월 + RNUM - 1 만큼 을 읽어 오도록 기술한다.
이렇게
TO_CHAR(ADD_MONTHS(TO_DATE('199906','YYYYMM'),RNUM-1),'YYYY.MM')
최종 문장은 아래와 같다.
SELECT RNUM,
TO_CHAR(ADD_MONTHS(TO_DATE('199906','YYYYMM'),
RNUM -1 ),'YYYY.MM')
FROM (SELECT ROWNUM RNUM FROM USER_TABLES)
WHERE ADD_MONTHS(TO_DATE('199906','YYYYMM'), RNUM -1 ) <=
TO_DATE('200004','YYYYMM')
여기에서 강제로 주어진 시작값과 끝값을 PARAMETER 값으로
바꾸면 상황에 따라 유용하게 쓰일 수 있을 것이다.
댓글 0
번호 | 제목 | 글쓴이 | 날짜 | 조회 수 |
---|---|---|---|---|
34 | 반올림 DATA의 오차보정 | 운영자 | 2002.09.18 | 3585 |
33 | 복제를이용한 합계계에서 비율계산 | 운영자 | 2002.09.18 | 3669 |
32 | DATA변환 | 운영자 | 2002.09.18 | 2750 |
» | 중간값구하기 | 운영자 | 2002.09.18 | 3377 |
30 | 한번 읽은 테이블로 백분율 구하기 | 운영자 | 2002.09.18 | 4085 |
29 | 빠진이빨찾기 III | 운영자 | 2002.09.18 | 3359 |
28 | 빠진이빨찾기 II | 운영자 | 2002.09.18 | 3067 |
27 | 빠진이빨찾기 | 운영자 | 2002.09.18 | 3122 |
26 | 순환참조에서의 상위코드로집계 | 운영자 | 2002.09.18 | 3226 |
25 | CONNECT BY의 SORT와 JOIN | 운영자 | 2002.09.18 | 2811 |
24 | REPORT 양식맞추기4 | 운영자 | 2002.09.18 | 2597 |
23 | REPORT 양식 맞추기 III | 운영자 | 2002.09.18 | 3015 |
22 | REPORT 양식 맞추기 II | 운영자 | 2002.09.18 | 2646 |
21 | REPORT 양식 맞추기 | 운영자 | 2002.09.18 | 31359 |
20 | 1:1 JOIN / 1:M JOIN | 운영자 | 2002.09.18 | 3000 |
19 | TUNING-01 | 운영자 | 2002.09.18 | 2739 |
18 | 소계와 합계 | 운영자 | 2002.09.18 | 3489 |
17 | 중복DATA 찾아내기 | 운영자 | 2002.09.17 | 2817 |
16 | GROUP별 DATA 분류 | 운영자 | 2002.09.17 | 2982 |
15 | PARAMETER값에 따라 변경이 일어나는 문장 | 운영자 | 2002.09.17 | 15808 |