DECODE는 오라클에서 지원하는 내장 함수입니다. 일반 어플리케이션의 IF... ELSE와 비슷한 문법구조를

가지나, 훨씬 간결하고 표현이 용이한 장점이 있습니다. 또한, 기호를 잘 활용하면 가독성도 용이해집니다.

간단하게 DECODE를 살펴보겠습니다.


DECODE(DEPRCD, 1, '영업부','기타부서')

위의 DECODE는 실제 테이블에 데이터가 1,2,3,4,5.... 이렇게 다양한 부서가 있을 경우에 우리가

조회하고 싶은 데이터는 1인 영업부만을 부서로, 나머지는 기타로 몰아서 데이터를 보고 싶다는 의미입니다.

실제, 이 DECODE문장은 SELECT/WHERE/GROUP BY/HAVING/ORDER BY등 모든 절에 다 올수 있지만,

그 사례는 다음장에서 보기로 하고 일단, 기능에 대해서만 살펴보기로 하죠. 위 문장을 글자로 풀어내면

"부서코드가 1이면 영업부로, 그외의 데이터는 기타로 몰아달라는 것입니다.

설령 부서코드가 NULL이라 하더라도 기타로 들어가게 됩니다. 이후, NULL에 대한 강좌에서

NULL값에 대한 의미를 다시한번 확인하기로 하고, 위의 경우처럼 코드를 기준으로 가지고 데이터를

표현하는 경우에 DECODE는 짧고 간결하게 그 값을 나타낼 수 있습니다. 그렇다면, 이런 경우는 어떨까요?

관리부장님의 요구사항이 들어왔습니다.

"우리 회사에서 근무하는 직원들의 월급을 3단계로 나누어서 보고 싶다네...

100만원 미만이면 하,100~200만원이면 중,200만원이상은 상 이렇게 데이터를 보여주게나"

라고 말하고 가십니다. DECODE는 EQUAL처리 밖에 할수가 없기 때문에,

개발자는 고민에 빠지게 될 것입니다. 물론 SQL을 많이 사용해본 개발자라면 SIGN이라는함수가 있다는

것을 알기 때문에 다음과 같이 그 해답을 찾게될 것입니다.

DECODE(FLOOR(SALARY/1000000),0,'하',1,'중',2,'상')

그러나, 위와 같이 DECODE문장을 사용할 경우는 중요한 데이터를 놓칠 가능성이 있습니다.

만일, 월급이 3백만원을 넘는 직원이 존재하는 경우는 어떻게 해야할까요..

물론, DECODE(FLOOR(900000/1000000),0,'하',1,'중',2,'상',3,'상') 라는 방법으로 상중하를 나누어

줄 수는 있습니다. 그러나, 4백만원을 넘는 직원이 나오면 또 붙여야 할까요? 이것은 문제가 있습니다. 그래서,

다음과 같이 SQL을 다시 개량하게 됩니다.

DECODE(SIGN(FLOOR((SALARY-1000000)/1000000)),-1,'',0,'',1,')

이제 2백만원을 넘는 직원에 대해서는 그 급여가 얼마이든 상으로 표현할 수 있게 되겠네요.

하지만 살펴봅시다. 한개의 직원 데이터 급여의 상중하를 구분해 내기 위해서, FLOOR와 SIGN,DECODE를

각각 수행해 봐야 하는 상황이 발생합니다. 더구나 빼고 더하고 산수기호 처럼 햇갈리죠...

거기다 산술연산의 우선순위(굳이 언급 하지는 않겠습니다)까지 고려해야 한다면 복잡한 쿼리일 경우

오히려 가독성이 떨어질 수 있습니다. 이러한 이유로 ANSI-92에서 제시된 새로운 표현방법이 CASE문입니다.

CASE문에서는 위와 같은 문장을 아래와 같이 해소할 수 있습니다.


CASE  WHEN SALARY < 1000000                                  THEN '하'
          WHEN SALARY >= 1000000 AND SALARY < 2000000 THEN '중'
          WHEN SALARY < 2000000                                  THEN '상'
  END

이제 복잡한 덧셈뺄샘도, 나누기와 몫을 구하는 함수도 기억할 필요가 없습니다. 다만,

CASE문장을 어떻게 쓰는지는 기억해야 합니다. 그러나, CASE문장이 DECODE문장 보다는

훨씬 그 표현해야 하는 내용이 길어졌죠? 그게 CASE문의 단점입니다.

따라서, EQUAL에 의한 데이터처리가 가능한 경우에는 DECODE가, RANGE에 의한 데이터 분류가

필요한 경우는 CASE가 유리할수 있겠습니다. 이런 방식으로 나누어서 사용하신다면 훨씬 더 효과적이겟죠?



'먹고살기 > Oracle' 카테고리의 다른 글

SQL -- Analytic Function  (0) 2011.08.10
GROUP BY의 고급 응용  (0) 2011.08.10
Oracle case문  (0) 2011.08.10
oracle case when ~ then~ else end  (0) 2011.08.10
Oracle Sql Case 사용법  (0) 2011.08.10
Oracle case문 먹고살기/Oracle 2011. 8. 10. 10:28

참조: where구에 case문을 써 보자

지금까지는 oracle 독자 함수인 decode를 많이 사용했는데

이제는 표준 sql문에 case문이 있으니

나도 서서히 case문을 사용하는 편으로 바꿔야겠다.

아래의 두 가지 사용방법이 있다.

if-else 와 같은 사용법

SELECT

CASE
WHEN ROUND_METHOD <= 0 THEN FLOOR(c_data.BASE_AMOUNT * RATE)
WHEN ROUND_METHOD >= 2 THEN CEIL(c_data.BASE_AMOUNT * RATE)
WHEN ROUND_METHOD > 0 THEN ROUND(c_data.BASE_AMOUNT * RATE, ROUND_DIGIT)
END
INTO l_UNEMPLOYMENT_INSURANCE
FROM ACCOUNT_M_002
WHERE PERIOD_VALIDITY_FROM <= SYSDATE
AND PERIOD_VALIDITY_TO >= SYSDATE
;

switch 와 같은 사용법

SELECT

CASE ROUND_METHOD
WHEN 0 THEN FLOOR(c_data.BASE_AMOUNT * RATE)
WHEN 1 THEN CEIL(c_data.BASE_AMOUNT * RATE)
WHEN 2 THEN ROUND(c_data.BASE_AMOUNT * RATE, ROUND_DIGIT)
END
INTO l_UNEMPLOYMENT_INSURANCE
FROM ACCOUNT_M_002
WHERE PERIOD_VALIDITY_FROM <= SYSDATE
AND PERIOD_VALIDITY_TO >= SYSDATE
;

▶ 메모

1. else는 생략 가능하지만, 생략되었다면 NULL을 리턴한다.

2. microsoft ACCESS에서는 지원하지 않는다.

3. switch 와 같은 사용법은 if-else 와 같은 사용법의 생략 스타일이라고 볼수 있다.

그러므로 아마도 if-else 와 같은 사용법만 알아두면 될 것 같다.

4. when 조건평가에 있어서, 참이 되는 when이 발견되면 그 밑에 더 정확한 when이 있다고 하더라도

더 이상 처리를 하지 않기에 이 점을 의식하여 case문이 작성할 필요가 있다.

5. performance에 관한 얘기

http://blog.naver.com/json2811/90080666948

[출처] Oracle case문|작성자 제이슨

'먹고살기 > Oracle' 카테고리의 다른 글

GROUP BY의 고급 응용  (0) 2011.08.10
DECODE와 CASE WHEN ...  (0) 2011.08.10
oracle case when ~ then~ else end  (0) 2011.08.10
Oracle Sql Case 사용법  (0) 2011.08.10
[오라클] SQL - UNION에 관한 SQL 규칙  (0) 2011.07.19

CASE 컬럼명 | 표현식 WHEN 조건식1 THEN 결과1
WHEN 조건식2 THEN 결과2
.......
WHEN 조건식n THEN 결과n
ELSE 결과
END

조건문과 조건문 사이에는 콤마(,) 를 사용하지 않는다.
CASE 문은 반드시 END 로 끝내야 한다.
CASE 표현식은 ANSI SQL 형식도 지원한다.
결과 부분은 NULL 을 사용해서는 안된다.

ex>

하나의 컬럼으로 여러가지 값을 비교하고 싶다면

SELECT CASE 'ABC' WHEN 'ABC' THEN 'OK_STRING!!'

WHEN 'BBC' THEN 'NO_STRING!!'

ELSE 'NO_STRING!!'

END AS 별명별명
FROM dual

여러조건을 비교하고 싶다면

SELECT CASE WHEN 'A'<'B' THEN 'B WIN!!'

WHEN 'C'<'D' THEN 'D_WIN!!'

ELSE 'NO_STRING!!'

END AS 별명별명

FROM dual

이런식으로 사용하면 된다.

비교할때에 소문자하고 대문자하고 비교하면 비교('a'와 'A'는 다르다.)

한마디로 대소문자 비교한다는 말이다.

근데 'a'>'A'이다.. 소문자가 더 크게나온다.

문자열이 어케 되는지는 모르겠다..

'먹고살기 > Oracle' 카테고리의 다른 글

DECODE와 CASE WHEN ...  (0) 2011.08.10
Oracle case문  (0) 2011.08.10
Oracle Sql Case 사용법  (0) 2011.08.10
[오라클] SQL - UNION에 관한 SQL 규칙  (0) 2011.07.19
ORACLE ROWNUM 활용  (0) 2011.07.08

보통 코딩을 할 경우 조건문을 사용 해서 처리하는 부분들이 많이있다.

Oracle에서는 Case 구문을 사용하는데

Case when 조건 then 조건문에 맞을 경우 수행 when 조건 then 수행 else 아닐경우 end as 명칭

이렇게 사용한다.

예를 들면 다음과 같다.

SELECT CODE_TYPE, CODE, CODE_NAME, DESCRIPTION, CREATEDATE, MODIFYDATE,
CASE WHEN PARENT_SEQ = '142' AND SUBSTR(CODE,0,1) = 'F' THEN '1'
WHEN PARENT_SEQ = '142' AND SUBSTR(CODE,0,1) = 'H' THEN '2'
ELSE PARENT_SEQ
END AS PARENT_SEQ
, SEQ
FROM ORABPEL.CODE_T

위의 구문을 해석해보면 parent_seq 가 142이면서 code의 첫번째 값이 F 인경우 1을 출력,

parent_seq가 142이면서 code의 첫번째 값이 H인경우 2를 출력,

이도 저도 아닐경우 그대로 출력

출력한 값은 parent_seq라 명칭을 붙인다.

라고 해석 할 수 있다.

[출처] Oracle Sql Case 사용법|작성자 태무

'먹고살기 > Oracle' 카테고리의 다른 글

Oracle case문  (0) 2011.08.10
oracle case when ~ then~ else end  (0) 2011.08.10
[오라클] SQL - UNION에 관한 SQL 규칙  (0) 2011.07.19
ORACLE ROWNUM 활용  (0) 2011.07.08
EXP-00091  (0) 2011.07.08

[오라클] SQL - UNION에 관한 SQL 규칙

Head First SQL 책에 있는 UNION에 관한 내용을 보다가 이 내용을 참고로 다시 정리해 봅니다.

1. UNION에서 ORDER BY 사용

- UNION에서 ORDER BY가 여러 번 나오면 해석하지 못한다는 에러가 발생한다.

- UNION은 문장의 끝에 한 개의 ORDER BY만을 받아 들일 수 있다.

이유는 UNION이 여러 SELECT문의 결과를 합친 후 결과를 만들기 때문이다.

예제 1) 두 select문에 order by 가 모두 있을 경우 에러가 발생한다.

select 10 as a1, 20 as a2 from dual order by a1

union

select 30 as a3, 40 as a4 from dual order by a1

예제 2) 두 select문에 order by 가 마지막 select 문에만 있어야 한다.

select 10 as a1, 20 as a2 from dual

union

select 30 as a3, 40 as a4 from dual order by a1

- ORDER BY 절에 컬럼명은 첫번째 질의(select문)의 컬럼명만 사용이 가능하다.

예제 3) 이런 경우는 두번째 select문의 컬럼명을 사용했기 때문에 에러가 발생한다.

select 10 as a1, 20 as a2 from dual

union

select 30 as a3, 40 as a4 from dual order by a3

예제 4) 첫번째 select문의 컬럼명을 사용하였기에 정상 처리

select 10 as a1, 20 as a2 from dual

union

select 30 as a3, 40 as a4 from dual order by a1

2. 각 SELECT문의 열(컬럼) 수는 같아야 한다.

- 첫번째 SELECT문에서 두 열을 선택하고 두번째에서는 하나의 열을 선택 할 수 없다.

예제) 위 내용처럼 각 SELECT문의 열의 수가 다를 경우 에러가 발생한다.

select 10 as a1, 20 as a2 from dual

union

select 10 as a3 from dual

- 컬럼 수가 일치하지 않아 에러가 발생할 경우 강제로 일치 시키는 방법은 상수값 또는 NULL을 사용한다.

select 10 as a1, 20 as a2 from dual

union

select 10 as a3, NULL from dual

3. 각 SELECT문에 표현식과 집계 함수도 같아야 한다.

4. SELECT문의 순서는 중요하지 않다. 순서는 결과에 영향을 미치지 않는다

보기 1)

select 10 as a1, 20 as a2 from dual

union

select 30 as a1, 40 as a2 from dual

보기 2)

select 30 as a1, 40 as a2 from dual

union

select 10 as a1, 20 as a2 from dual

보기1)과 보기2)는 SELECT문의 순서가 달라도 결과는 같다는 뜻이다.

5. UNION의 결과에서 중복값은 하나로 나오는 것이 디폴트이다.

중복값이 모두 나오게 하려면 UNION ALL를 쓰면 된다.

6. 열의 데이터 타입은 같거나 서로 변환 가능한 값이어야 한다.

여기서 좀더 생각할 것은 데이터 타입만 같으며 되며 데이터 사이즈까지 같을 필요는 없다는 것이다.

예를 들어 같은 열에서 하나는 varchar2(100) 이고 다른 하나는 varchar2(200)인 경우라도 문제가 없다.

7. 컬럼명은 일치하지 않아도 된다. 그래서 강제로 컬럼명을 맞춘다고 해도 무조건 순서대로 컬럼명을 맞추기 때문에 이점을 유념하고 있어야 한다. 컬럼명이 다를 경우 첫번째 질의에 있는 컬럼명이 헤딩된다.

예제 1) 컬럼 순서를 바꾸고 강제로 alias를 준다고 해도 sum(a1)은 "50"이 아니라 "40"이 나온다.

select sum(a1), sum(a2)

from (

select 10 as a1, 20 as a2 from dual

union

select 30 as a2, 40 as a1 from dual

)

8. UNION은 내부적으로 중복된 값을 제거하는 과정에서 SORT기능(정렬)이 작동하며,

UNION ALL은 중복여부 관계없이 전체가 보여주므로 SORT가 일어나지 않는다.

고로 UNION ALL이 빠르다.

'먹고살기 > Oracle' 카테고리의 다른 글

oracle case when ~ then~ else end  (0) 2011.08.10
Oracle Sql Case 사용법  (0) 2011.08.10
ORACLE ROWNUM 활용  (0) 2011.07.08
EXP-00091  (0) 2011.07.08
[Oracle] distinct, rowid 중복 제거, 최신 데이터 하나만 가져오기  (1) 2011.06.30