역시나 sqlleader.co.kr 에서 주고받은 글...

---------

제 목   Re) NULL 데이터와 ? : 3항 연산자와 파생열 변환이 함께 쓰였을 때 이상한 동작
· 작성자    한대성
· 글정보   Hit : 7, Date : 2007/02/23 00:32

Null에 대한 처리로 인한 것 같습니다..
 
(is_dnt_goods_yn1 == "Y") ? "Y" : "N"
의 조건식에서 is_dnt_goods_yn1이 NULL 인 경우에는 "N"이 아닌 NULL로 처리됩니다.
 
NULL 이 "Y"는 아니지만, 그렇다고 해서 "Y"가 아닌 것도 아니기 때문에..
 
말씀하신 조건에 대한 조건식은 다음과 같이 하면 어떨까 합니다..
 
is_dnt_goods_yn2 == "A" && !ISNULL(is_dnt_goods_yn2) ? "A" : (is_dnt_goods_yn1 == "Y" && !ISNULL(is_dnt_goods_yn1) ? "Y" : "N")
 
조건 중에 "A가 아니면, ... Y가 아니면..." 이라는 조건 때문에 단순히   !ISNULL()   로만 판단하면 안되지 않을까 생각되네요..^^
 
 




 
작성자 : 박노철 , 등록일 : 2007-02-22 오후 5:31:00
 
파생열 변환과 관련하여 아무래도 이해가 잘 되지 않는 점이 있어서 다시 질문드립니다. 다음과 같은 소스 데이터가 있습니다.
 
select * from is_dnt_goods_src
 
is_dnt_goods_yn1 is_dnt_goods_yn2
---------------- ----------------
Y                NULL
Y                NULL
Y                NULL
Y                NULL
Y                NULL
NULL             A
NULL             A
NULL             A
NULL             A
Y                NULL
Y                NULL
Y                NULL
Y                NULL
Y                NULL
Y                NULL
Y                NULL
NULL             A
NULL             A
NULL             A
NULL             A
NULL             A
NULL             A
Y                NULL
Y                NULL
Y                NULL
Y                NULL
Y                NULL
Y                NULL
 
여기서 필요한 비즈니스 로직은 is_dnt_goods_yn 이라는 필드값을 파생열 변환을 사용해서 새 열로 만들어내는데,
 
'is_dnt_goods_yn2 가 A 면 A를 리턴하고 A가 아니면(NULL이거나 다른값) 이면 is_dnt_goods_yn1 을 검사해서 그 값이 Y면 Y를 리턴하고 그게 아니면(NULL이거나 다른값) 이면 N 를 리턴한다'
 
입니다. 위의 로직을 파생열 변환에서 다음과 같이 구현해보았습니다.
 
is_dnt_goods_yn      <새열로 추가>   is_dnt_goods_yn2 == 'A' ? 'A' : ((is_dnt_goods_yn1 == 'Y') ? 'Y' : 'N')
 
결과는 다음과 같습니다.
is_dnt_goods_yn1 is_dnt_goods_yn2 is_dnt_goods_yn
---------------- ---------------- ---------------
Y                NULL             NULL
Y                NULL             NULL
Y                NULL             NULL
Y                NULL             NULL
Y                NULL             NULL
NULL             A                A
NULL             A                A
NULL             A                A
NULL             A                A
Y                NULL             NULL
Y                NULL             NULL
Y                NULL             NULL
Y                NULL             NULL
Y                NULL             NULL
Y                NULL             NULL
Y                NULL             NULL
NULL             A                A
NULL             A                A
NULL             A                A
NULL             A                A
NULL             A                A
NULL             A                A
Y                NULL             NULL
Y                NULL             NULL
Y                NULL             NULL
Y                NULL             NULL
Y                NULL             NULL
Y                NULL             NULL
 
A는 제대로 넘어오는데 Y값이 제대로 채워지지 않습니다. 아무래도 이상해서 파생열 변환의 expression 을 바꿨습니다.
 
!ISNULL(is_dnt_goods_yn2) ? is_dnt_goods_yn2 : (!ISNULL(is_dnt_goods_yn1) ? is_dnt_goods_yn1 : 'N')
 
NULL을 검사하도록 했죠. 그랬더니 다음과 같이 나왔습니다.
 
is_dnt_goods_yn1 is_dnt_goods_yn2 is_dnt_goods_yn
---------------- ---------------- ---------------
Y                NULL             Y
Y                NULL             Y
Y                NULL             Y
Y                NULL             Y
Y                NULL             Y
NULL             A                A
NULL             A                A
NULL             A                A
NULL             A                A
Y                NULL             Y
Y                NULL             Y
Y                NULL             Y
Y                NULL             Y
Y                NULL             Y
Y                NULL             Y
Y                NULL             Y
NULL             A                A
NULL             A                A
NULL             A                A
NULL             A                A
NULL             A                A
NULL             A                A
Y                NULL             Y
Y                NULL             Y
Y                NULL             Y
Y                NULL             Y
Y                NULL             Y
Y                NULL             Y
 
정확한 결과가 나왔습니다.
 
제가 expression 을 잘못 사용한 것일까요? 3항 연산자 evaluate 하는데 버그가 있는 것일까요? -_-;;;;
이거때문에 정말 한참을 헤맸습니다. 흑. 혹시 이런 경우를 겪어 보셨는지요????
 
 
 
 

박노철 아.. 그렇군요. 감사합니다. DB에서 적용되던 TRUE, FALSE, NULL 의 원리가 SSIS 스크립트에서도 그대로 적용되는 모양이군요. 보통 프로그래밍 언어에서 하듯이 하면 될 줄 알았는데. 다시 한번 감사드립니다^^ 2007/02/23  

Posted by maceo

02 23, 2007 09:28 02 23, 2007 09:28
, ,
Response
No Trackback , No Comment
RSS :
http://merritt.co.kr/tt/rss/response/88

울회사 권병준 대리가 개발팀에 뿌린 가이드. 실수하기 쉬운 것임...

---------------------------------


안녕하세요. DB개발팀의 권병준입니다..

오늘도 찾아온 주의사항 한마디입니다.

역시나 길게 글 읽기 싫어하시는 분들을 위해 요약해서 한줄로 먼저 말씀드리겠습니다.

WHERE 조건에서 같은 컬럼에 대해 IS NOT NULL 조건과 <, >, <>, ANS SO ON.. 등의 조건을

같이 사용하지 마십시요.

-----------------------------------------------------------------------------

이제 설명 부분..

SP 검수하다보면 간간히 (A를 컬럼명이라고 가정합시다)

WHERE A IS NOT NULL AND A >= @YESTERDAY AND A <= @TODAY

와 같은 조건이 있는 경우가 있습니다.

물론, 해석은 A 가 NULL이 아니면서 어제와 오늘 사이의 값에 대한 조회.. 라는 건데,

저렇게 사용할 필요가 전혀 없습니다.

여기서 NULL 이라는 것에 대해 다시 한 번 재조명을 해보도록 하지요.

NULL 이라는 것은 값없음(이 아니라!) 미확정값이라는 뜻입니다.

아직 해당 컬럼에 값이 정해져있지 않다는 얘기죠. WHERE 조건에서

WHERE A >= @YESTERDAY 라고 조건을 주게 되면 당연히 어제 이후로의 확정된! 값에

대한
것만 조회를 해달라는 의미입니다. 여기서 미확정값은 당연히 제외가 되겠죠.

고로 저렇게 확정된 값에 대한 조회조건을 주면서 또다시 미확정된 값을 제외하라는 조

건을 주는건
CPU 부담만 증가시킬 뿐입니다. (Bookmark Lookup시에 꽤 부담을 주게 됩

니다.)

실제 간단한 실험을 통해서 비용적인 측면의 비교를 한 번 해 보겠습니다.

하나의 테이블을 만들고 여기에 테스트 값을 넣어줍니다.

CREATE TABLE NULL_TEST (
SEQ INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
NULL_COL INT NULL
)

DECLARE @CNT INT
SET @CNT = 1
WHILE @CNT < 5000
BEGIN
INSERT INTO NULL_TEST VALUES (NULL)
INSERT INTO NULL_TEST VALUES (@CNT)
SET @CNT = @CNT + 1
END

10000개의 데이터가 생성이 되었습니다. 여기서 제가 위에 말한 조회조건대로 IS NOT NULL이라는

조건을 추가로 준 것과 아닌 것에 대해서 각각 간단하게 조회를 해 봅니다.

SELECT * FROM NULL_TEST WHERE NULL_COL < 10 AND NULL_COL IS NOT NULL

SELECT * FROM NULL_TEST WHERE NULL_COL < 10



물론 결과값은 같습니다. 하지만 조회에 해당되는 비용은 다르게 나옵니다.

아래 그림을 봐 주십시요.



위의 쿼리와 아래의 쿼리 비용이 63.64% VS 36.36%로 차이가 나는 것을 보실 수 있을 겁

니다.
안 써도 되는 컬럼 추가로 인해 비용 차이가 이만큼이나 벌어졌습니다. 행 수가

많아지면
많아질수록 이 격차는 더욱 커집니다.

SP 작성하실 때에 여러분의 주의를 부탁드립니다. ^^

----------------------------------------------------------------------------

이건 좀 더 알고 싶으신 분들을 위해 추가합니다.

ANSI_NULLS 라는 옵션을 대부분 알고 계실 것입니다. 대부분의 DB에서는

(G마켓의 MS-SQL SERVER 포함) ANSI_NULLS ON 으로 사용합니다.

(NULL을 본래 그대로의 뜻인 미확정값으로 사용하겠다는 의미입니다.

MS-SQL SERVER에서는 NULL을 확정값처럼 사용하도록 할 수 있습니다.

특이한 옵션인거죠? ㅎㅎ (오라클 사용하던 저로서는 마냥 신기해했던 옵션입니다)

그렇다면..

SET ANSI_NULLS OFF 로 해주고 위의 쿼리를 다시 돌려보면 결과가 어떻게 나올까요?

............ 한 10초쯤 생각해 보시기 바랍니다. ...........................

예상하셨다시피 NULL 값을 확정값처럼 DB에서 생각하기 때문에

위의 두 쿼리는 아래처럼 같은 비용을 내게 됩니다.



하지만, 울회사에서는 ANSI_NULLS 를 ON 으로 주고 사용하기 때문에 여러분들은 역시

SP 작성하실 때에 주의를 기울여 주시지 않으면 안된다는 겁니다. ^^

결론 : 여러분의 작은 관심이 시스템을 조금 더 안정적으로 만들 수 있습니다.

그럼 또 좋은 '꺼리' 생기면 찾아뵙겠습니다. ㅎㅎ

Posted by maceo

10 19, 2006 19:16 10 19, 2006 19:16
,
Response
No Trackback , a comment
RSS :
http://merritt.co.kr/tt/rss/response/78


블로그 이미지

가늘어도 긴놈이 장땡

- maceo

Archives

Authors

  1. maceo

Calendar

«   3 2010   »
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31      

Site Stats

Total hits:
170227
Today:
18
Yesterday:
59