조건.
VAL1
----------
A97
B10
B12
TEST38 에 위와 같은 DATA 가 있다.
문제.
이미 빠진이빨찾기I 에서 다루었던 내용의 반복이다.
단지 이번 문제가 I과 다른점은 숫자로만 이루어진 값이
아니라는 것이다.
문제는 A00 에서 부터 Z99 까지의 값을 가질수 있다.
위의 값을 보면 MAX 값이 B12 이다.
해야할 일은 A00에서 B12 까지의 값중에서 TEST38 에서 갖고 있는
값을 제외한 나머지 값을 찾아내는 것이다.
A00 ~ A99 중 A97을 제외한 99개의 값과 B00 에서 B12중 B10과 B12를
제외한 11개의 값을 합친 총 110개의 값을 찾아내면 된다.
문자형태가 들어가는 것은 첫번째 자리에만 국한되며,뒤의 두자리는
숫자 형태의 일련값이 들어 간다.
즉 A99 뒤에 B00 이 온다는 것이다.
VAL1
----------
A00
A01
중략
A96
A98
A99
B00
중략
B07
B08
B09
B11
110 행이 선택되었습니다
결과가 위와 같이 나오면 된다.
빠진이빨찾기I 에서 사용한 방법을 사용한다.
생각.
문제를 해결하는 방법은 이미 빠진이빨찾기I 에서 다루었다.
다만 문자가 들어있어,단순히 숫자형태로만 들어있던 전번 경우와
다른점이 있다.
이 부분을 어떻게 해결하느냐가 문제의 열쇠가 될 것이다.
먼저 생각해 볼 수 있는 것은 문자가 들어있는 값을 숫자로
치환하여 일련의 값을 만든 후
다시 그 일련의 값들을 문자로 바꾸어 보여주는 방법을 생각해
볼 수 있다.
그렇지 않다면,
A 에 특정값을 더하면 B 를 RETURN 하는 함수를 만들어
사용할 수도 있다.
하지만 우리는 ORACLE 자체에서 제공하는 함수 만을 사용하여
문제를 풀어보자.
ORACLE 함수에는 ASCII() 라는 함수와 CHR() 이라는
함수가 있다.
ASCII() 는 주어진 문자의 ASCII 값을 RETURN 하며,
CHR() 는 주어진 ASCII 값에 해당하는 문자를 RETURN 한다.
이 정도만 알고 있다면 문제의 50%는 해결된것이나 다름없다.
이미 3자리 코드중 제일 앞 자리만이 A~Z 값을 가지며,
나머지 두자리는 숫자형태라는 것을 알고 있다.
코드는 A00 부터 시작한다는 것도 이미 알고있다.
A~Z까지가 결국은 100단위 이상의 자리값을 결정짓는다.
A는 100보다 작은 값 ,B는 100,C는 200......
과 같은 형태일 것이다.
결국 B를 100으로 치환하면 최대값은 100+12 가 된다.
112의 일련번호를 0번부터 만들어주는 일은 어렵지
않을 것이다.
만약 최대값이 C로 시작되는 코드였다면 200번대의 번호로
치환이 되었을 것이다.
이렇게 일련번호를 읽어놓고 그값을 계산해서 100보다 작으면 'A',
100번대이면 'B',200번대이면 'C' 를 첫번째 자리에 놓고 뒤에
100으로 나눈 나머지 값을 붙여주면 A00 에서 최대 코드까지의
일련의 코드가 만들어진다.
이중에서 TEST38에 존재하고 있는 DATA만 제외시키면
빠진이빨이다.
해법.
단계1.SELECT ASCII('A') FROM DUAL
위의 문장을 실행하면 65 라는 숫자를 RETURN 한다.
즉, 'A'의 ASCII 값이 65라는 얘기다.
그렇다면 최대코드의 첫번째 문자를 ASCII() 함수에
적용시킨후 그 값에서 65를 빼주면
'A' 는 0,'B' 는 1,'C' 는 2.....와 같은 값을 RETURN 한다.
다시 그 값에 100을 곱한 후 최대코드의 뒷부분 2자리를 더하면
최대코드값을 숫자로 치환한 값이 나온다.
이값은 우리가 문제를 해결하기 위해 우리의 규칙대로
치환한 값이다.
뒤에 동일 규칙을 역으로 적용하여 다시 문자로 만들어
줄 것이다.
문장을 구성하면 아래와 같이 된다.
SELECT (ASCII(SUBSTRB(MAX(VAL1),1,1)) - 65) * 100 +
TO_NUMBER(SUBSTRB(MAX(VAL1),2))
FROM TEST38
결과는 112 가 된다.
112라는 값은 'B12'의 숫자 치환 값이며 우리가 필요로하는
일련번호의 최대 값이기도 하다.
단계2.두번째로 할일은 단계1의 정보를 이용하여 영 부터 113개의
번호를 채취하는 일이다.
SELECT ROWNUM-1 NO
FROM USER_TABLES
WHERE ROWNUM-1 <= (SELECT (ASCII(SUBSTRB(MAX(VAL1),1,1))
- 65) * 100 +
TO_NUMBER(SUBSTRB(MAX(VAL1),2))
FROM TEST38)
결과는 0 에서 부터 112 까지 113개의 ROW의 번호가 읽혀온다.
단계3.이번 단계에서는 각 번호의 첫번째 자리를 문자로 바꿔 준다.
단계2의 문장을 INLINE VIEW 로 하여 다음과 같이 SELECT 한다.
CHR(65 + FLOOR(NO/100)) || LPAD(TO_CHAR(MOD(NO,100)),2,'0')
단계2의 정보가 첫번째 자리가 문자인 형태로 바뀐다.
그리고 MINUS 집합 연산자를 이용해 TEST38에 있는 DATA를
제외시키면 최종 문장은 아래와 같이 된다.
SELECT CHR(65 + FLOOR(NO/100)) ||
LPAD(TO_CHAR(MOD(NO,100)),2,'0') VAL
FROM (SELECT ROWNUM-1 NO
FROM USER_TABLES
WHERE ROWNUM-1 <=
(SELECT (ASCII(SUBSTRB(MAX(VAL1),1,1))-65)
* 100 +
TO_NUMBER(SUBSTRB(MAX(VAL1),2))
FROM TEST38))
MINUS
SELECT VAL1 FROM TEST38
물론 결과는 문제에 있는 답과 동일하다.
VAL1
----------
A97
B10
B12
TEST38 에 위와 같은 DATA 가 있다.
문제.
이미 빠진이빨찾기I 에서 다루었던 내용의 반복이다.
단지 이번 문제가 I과 다른점은 숫자로만 이루어진 값이
아니라는 것이다.
문제는 A00 에서 부터 Z99 까지의 값을 가질수 있다.
위의 값을 보면 MAX 값이 B12 이다.
해야할 일은 A00에서 B12 까지의 값중에서 TEST38 에서 갖고 있는
값을 제외한 나머지 값을 찾아내는 것이다.
A00 ~ A99 중 A97을 제외한 99개의 값과 B00 에서 B12중 B10과 B12를
제외한 11개의 값을 합친 총 110개의 값을 찾아내면 된다.
문자형태가 들어가는 것은 첫번째 자리에만 국한되며,뒤의 두자리는
숫자 형태의 일련값이 들어 간다.
즉 A99 뒤에 B00 이 온다는 것이다.
VAL1
----------
A00
A01
중략
A96
A98
A99
B00
중략
B07
B08
B09
B11
110 행이 선택되었습니다
결과가 위와 같이 나오면 된다.
빠진이빨찾기I 에서 사용한 방법을 사용한다.
생각.
문제를 해결하는 방법은 이미 빠진이빨찾기I 에서 다루었다.
다만 문자가 들어있어,단순히 숫자형태로만 들어있던 전번 경우와
다른점이 있다.
이 부분을 어떻게 해결하느냐가 문제의 열쇠가 될 것이다.
먼저 생각해 볼 수 있는 것은 문자가 들어있는 값을 숫자로
치환하여 일련의 값을 만든 후
다시 그 일련의 값들을 문자로 바꾸어 보여주는 방법을 생각해
볼 수 있다.
그렇지 않다면,
A 에 특정값을 더하면 B 를 RETURN 하는 함수를 만들어
사용할 수도 있다.
하지만 우리는 ORACLE 자체에서 제공하는 함수 만을 사용하여
문제를 풀어보자.
ORACLE 함수에는 ASCII() 라는 함수와 CHR() 이라는
함수가 있다.
ASCII() 는 주어진 문자의 ASCII 값을 RETURN 하며,
CHR() 는 주어진 ASCII 값에 해당하는 문자를 RETURN 한다.
이 정도만 알고 있다면 문제의 50%는 해결된것이나 다름없다.
이미 3자리 코드중 제일 앞 자리만이 A~Z 값을 가지며,
나머지 두자리는 숫자형태라는 것을 알고 있다.
코드는 A00 부터 시작한다는 것도 이미 알고있다.
A~Z까지가 결국은 100단위 이상의 자리값을 결정짓는다.
A는 100보다 작은 값 ,B는 100,C는 200......
과 같은 형태일 것이다.
결국 B를 100으로 치환하면 최대값은 100+12 가 된다.
112의 일련번호를 0번부터 만들어주는 일은 어렵지
않을 것이다.
만약 최대값이 C로 시작되는 코드였다면 200번대의 번호로
치환이 되었을 것이다.
이렇게 일련번호를 읽어놓고 그값을 계산해서 100보다 작으면 'A',
100번대이면 'B',200번대이면 'C' 를 첫번째 자리에 놓고 뒤에
100으로 나눈 나머지 값을 붙여주면 A00 에서 최대 코드까지의
일련의 코드가 만들어진다.
이중에서 TEST38에 존재하고 있는 DATA만 제외시키면
빠진이빨이다.
해법.
단계1.SELECT ASCII('A') FROM DUAL
위의 문장을 실행하면 65 라는 숫자를 RETURN 한다.
즉, 'A'의 ASCII 값이 65라는 얘기다.
그렇다면 최대코드의 첫번째 문자를 ASCII() 함수에
적용시킨후 그 값에서 65를 빼주면
'A' 는 0,'B' 는 1,'C' 는 2.....와 같은 값을 RETURN 한다.
다시 그 값에 100을 곱한 후 최대코드의 뒷부분 2자리를 더하면
최대코드값을 숫자로 치환한 값이 나온다.
이값은 우리가 문제를 해결하기 위해 우리의 규칙대로
치환한 값이다.
뒤에 동일 규칙을 역으로 적용하여 다시 문자로 만들어
줄 것이다.
문장을 구성하면 아래와 같이 된다.
SELECT (ASCII(SUBSTRB(MAX(VAL1),1,1)) - 65) * 100 +
TO_NUMBER(SUBSTRB(MAX(VAL1),2))
FROM TEST38
결과는 112 가 된다.
112라는 값은 'B12'의 숫자 치환 값이며 우리가 필요로하는
일련번호의 최대 값이기도 하다.
단계2.두번째로 할일은 단계1의 정보를 이용하여 영 부터 113개의
번호를 채취하는 일이다.
SELECT ROWNUM-1 NO
FROM USER_TABLES
WHERE ROWNUM-1 <= (SELECT (ASCII(SUBSTRB(MAX(VAL1),1,1))
- 65) * 100 +
TO_NUMBER(SUBSTRB(MAX(VAL1),2))
FROM TEST38)
결과는 0 에서 부터 112 까지 113개의 ROW의 번호가 읽혀온다.
단계3.이번 단계에서는 각 번호의 첫번째 자리를 문자로 바꿔 준다.
단계2의 문장을 INLINE VIEW 로 하여 다음과 같이 SELECT 한다.
CHR(65 + FLOOR(NO/100)) || LPAD(TO_CHAR(MOD(NO,100)),2,'0')
단계2의 정보가 첫번째 자리가 문자인 형태로 바뀐다.
그리고 MINUS 집합 연산자를 이용해 TEST38에 있는 DATA를
제외시키면 최종 문장은 아래와 같이 된다.
SELECT CHR(65 + FLOOR(NO/100)) ||
LPAD(TO_CHAR(MOD(NO,100)),2,'0') VAL
FROM (SELECT ROWNUM-1 NO
FROM USER_TABLES
WHERE ROWNUM-1 <=
(SELECT (ASCII(SUBSTRB(MAX(VAL1),1,1))-65)
* 100 +
TO_NUMBER(SUBSTRB(MAX(VAL1),2))
FROM TEST38))
MINUS
SELECT VAL1 FROM TEST38
물론 결과는 문제에 있는 답과 동일하다.
댓글 0
번호 | 제목 | 글쓴이 | 날짜 | 조회 수 |
---|---|---|---|---|
66 | 부등호 조인 | 운영자 | 2002.09.18 | 56705 |
65 | 행렬(matrix)계산을위한 준비 | 운영자 | 2002.09.18 | 3061 |
64 | 최대값과 해당해의 다른값 가져오기 | 운영자 | 2002.09.18 | 3221 |
63 | DATA 병합 | 운영자 | 2002.09.18 | 2578 |
62 | 다수 NULL 허용 COLUMN의 명칭을 가져올때 | 운영자 | 2002.09.18 | 3732 |
61 | 수식이용 | 운영자 | 2002.09.18 | 2738 |
60 | JOIN과 SUBQUERY가 동일한 예제 | 운영자 | 2002.09.18 | 2950 |
59 | NULL과 0 의 AVG 차이 비교 | 운영자 | 2002.09.18 | 2875 |
58 | 고정된 Row 수 유지 | 운영자 | 2002.09.18 | 4228 |
57 | 두개 RECORD를 한행에 DISPLAY 시키기 | 운영자 | 2002.09.18 | 3162 |
56 | LENGTH/LENGTHB,SUBSTR/SUBSTRB,INSTR/INSTRB | 운영자 | 2002.09.18 | 4292 |
55 | 한줄에 2 ROW 보여주기 변형II | 운영자 | 2002.09.18 | 3109 |
54 | 상호간 OUTER 조인의 해결방안 | 운영자 | 2002.09.18 | 2941 |
53 | 선택적조인 | 운영자 | 2002.09.18 | 2961 |
52 | 반올림 DATA의 오차보정 | 운영자 | 2002.09.18 | 3585 |
51 | 복제를이용한 합계계에서 비율계산 | 운영자 | 2002.09.18 | 3669 |
50 | DATA변환 | 운영자 | 2002.09.18 | 2750 |
49 | 중간값구하기 | 운영자 | 2002.09.18 | 3377 |
48 | 한번 읽은 테이블로 백분율 구하기 | 운영자 | 2002.09.18 | 4085 |
» | 빠진이빨찾기 III | 운영자 | 2002.09.18 | 3359 |