case when절 사용에 대한 질문입니다 0 14 5,177

by 될때까지 [SQL Query] [2013.08.21 16:38:21]



가변조건 처리(전체, 일부)를 하라는 교육과제를 받아서
전체 가변조건 처리에 대한 쿼리를 아래와 같이 작성했습니다
select *
from test
where test_date = case when :param is null then test_date else :param end
실행해보니 예상대로 :param 값을 입력하지 않으니 그냥 테이블의 모든 값이 출력 되었습니다

그런데 쿼리를 아래와 같이
select *
from test
where test_date = case :param when null then test_date else :param end
바꿔보니, :param 값을 입력하지 않으니 아무것도 출력이 되지를 않네요

무슨차이로 그렇게 되는건가요?
제가 이해하기로는 case :param when null 로 바꿔도 동일하게 실행이 되야 맞는게 아닌가 싶은데...
by 될때까지 [2013.08.21 16:42:18]

질문하지 않고 넘어가도 될 부분이겠지만, 제 예상과 다르게 값이 출력 된다는 것이 제가 뭔가 이해를 잘못하고 있는 부분이 있는 것 같다 싶어서 질문드렸습니다 오늘 질문이 좀 많아서 죄송합니다

by 우리집아찌 [2013.08.21 16:48:01]

SELECT
   case when '' is null then 'test_date' else '' end  as V1
 , case '' when null then 'test_date' else '' end as v2
FROM DUAL

결과
V1 = 'test_date'
V2 = ''

결론
select *
from test
where test_date  = test_date
-----------------------------------------------------
select *
from test
where test_date  = ''

by 손님 [2013.08.21 16:50:20]

select *
from test
where test_date = case when :param is null then test_date else :param end
실행해보니 예상대로 :param 값을 입력하지 않으니 그냥 테이블의 모든 값이 출력 되었습니다

---> :param 값을 입력하지 않으면 then의 test_date
  where test_date = test_date (참) 전체 데이터 추출

select *
from test
where test_date = case :param when null then test_date else :param end
바꿔보니, :param 값을 입력하지 않으니 아무것도 출력이 되지를 않네요

----> case 조건식(참, 거짓) 조건이 없으니 else :param(값을 입력하지 않았으니 null)
where test_date = null <--- (null를 찾기 위한 구분은 where test_date is null)
where test_date = null로 처리되었기 때문에 아무것도 출력이 안됨.

by 미카엘 [2013.08.21 16:51:49]
헐 로그인 안하고 댓글 올려네요. -.-

by 마농 [2013.08.21 17:07:37]
안될때는 왜 안될지를 알아야 하는데...
Where 절의 Case 가 어떻게 동작하는지 궁금하다면?
Where 절은 없애고 Case 문을 그대로 Select 절에 넣어서 결과를 확인해보세요.

오라클에서 Null 에 대한 이해가 필요한데요.
Null 은 비교식에 사용하면 원하는 결과를 얻기 힘들고요
함수중에서도 널에 대한 처리를 해주는 함수가 있는 반면에 그렇지 않은 함수도 많습니다.
각각의 함수에서 널을 어떻게 처리하는지 알아야 합니다.
Case 문에서는 널비교가 안되구요, 반면에 Decode 문에서는 널비교가 됩니다.
DECODE(:param, null, test_date, :param)
대부분의 함수가 널에 대한 처리를 지원하지 못합니다.
널이 포함되는 계산식에서는 항상 주의를 기울여야 합니다.

by 될때까지 [2013.08.21 17:13:12]

엇 댓글 달고 있는 사이에 마농님이 댓글 달아주셨네요
궁금했던 내용 확실히 해결됐습니다 감사드립니다
null에 대해서는 아직 교육진도가 안나가서 지식이 부족했는데(선행학습 금지라.. ㅠㅠ)
case 에서는 null을 비교하면 안되는거였군요!


by 마농 [2013.08.21 17:15:24]
한가지 더 주의사항이 있습니다.
위에 사용하신 방법은 test_date 항목에는 널이 없다고 가정하고 하는 방법입니다.
널이 저장되어 있다면 전체조회시 누락되겠지요.(왜? 널은 비교가 안되니까...)
요런 방법도 있습니다.
WHERE ( :param IS NULL OR (:param IS NOT NULL AND test_date = :param) )

by 될때까지 [2013.08.21 17:36:49]
오라클에서는 null 비교가 안되기 때문에 test_date에 널값이 있는 경우,
then test_date 자체가 널값 때문에 누락된다는 말씀이신건가요?
제대로 이해한 것 같긴한데 자신이 없으니 한번 더 확인받고 넘어가고 싶네요.. ㅠㅠ
그리고 자꾸 질문에 질문을 하게 되서 죄송한데
where :param is null or (:param is not null and test_date = :param)
만 해도 되지 않나요? 괄호로 한번 더 묶어주는 이유가 무엇인지요?

by 마농 [2013.08.22 09:08:16]
test_date 에 널이 있다면
전체 조회시 널인 행은 조건이 null = null 이 되어 버리죠.
이러면 거짓이 되어 해당 행은 제외가 되겠지요.
이렇게 되면 전체조회하려던 예상과 빗나가게 되는거죠.

OR 조건을 괄호로 묶은 것은
조건이 그것뿐이라면 괄호가 없어도 되겠지만
다른 조건이 AND 로 더 연결될수도 있으므로 괄호로 묶은 것입니다.
OR 는 항상 괄호로 묶는 습관을 가지고 있습니다.
자칫 괄호로 묶지 않으면 원치 않는 결과를 초래하기도 하지요.
예를 들어 a or b and c 라는 조건과 (a or b) and c 라는 조건은 전혀 다른 결과를 냅니다.
a or b and c 는 괄호로 표시하면 a or (b and c) 이렇게 됩니다.
AND 가 OR 보다 연산순서가 빠르죠.

by 될때까지 [2013.08.22 09:20:49]

그렇군요
추후에 수정을 하거나 할 때도 깜빡하고 괄호 없이 다른 조건을 연결한다거나 하는 실수를 미연에 방지할 수도 있겠네요
오늘도 좋은 배움 얻어갑니다
감사합니다


by 될때까지 [2013.08.21 17:08:07]

우리집아찌님, 미카엘님 두분 모두 감사드립니다
제가 질문을 조금 잘못했나봅니다
제가 궁금한 점은

첫번 째 쿼리의 case문 내용을 해석해보면,
case when :param is null --:param 의 값이 null이면 then 추출, 아니면 else 추출
--따라서 :param 값 미입력 시 null이므로 then 추출 -> 전체데이터 출력 됨
두번 째 쿼리의 case문 내용을 해석해보면,
case :param when null --:param 의 값과 null을 비교하여 같으면 (결국, :param이 null이면) then 추출, 아니면 else 추출
--따라서 :param 값 미입력 시 null 이므로 when 절의 null 과 비교했을 때 같으므로 then 추출 -> 전체데이터 출력 됨
입니다
그런데 결과가 다른 것을 보니 두번 째 해석을 제가 잘못한 것 같은데 해석을 잘못했다는 것은 이해를 잘못했다는 뜻이니... 알고 넘어가고 싶어서요...
요약하자면, 그렇게 출력이 된다는 것 자체는 이해를 했습니다
그런데 두번째 쿼리의 경우 왜? 에 대한 질문을 스스로 던져봤을 때 이해가 안됩니다...
case 내용 when 비교, case when 내용에 대한 조건식
아니었나요?

by 미카엘 [2013.08.21 17:14:12]
case 구문 when 비교, case when 내용에대한 조건식 맡습니다.

제가 말씀드린건 null 비교시 = 비교가 아니고 오라클에서는 is null이라는 글을 올린거에요.

by 우리집아찌 [2013.08.21 17:25:12]
WHERE a = NULL (x)
WHERE a IS NULL (O)

by 될때까지 [2013.08.21 17:27:45]

감사합니다 이제 정확히 이해했습니다
제가 생초보라 풀이 된 설명을 봐야만 이해가 되네요 죄송합니다..

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입