널이 될 수있는 열로 불평등을 테스트합니다
문제
그래서 나는 물었다 의문 오늘 아침, 나는 올바르게 표현하지 않았으므로 왜 Null이 Null/False를 줄 수 있는지에 대한 많은 응답을 얻었습니다.
나의 실제 질문은, DB Guys가 둘 다 null이 될 수있는 두 개의 열에 대한 불평등을 테스트하는 시간의 명예로운 패션은 무엇입니까? 내 질문은 이것과 정반대입니다 의문.
요구 사항은 다음과 같습니다. A와 B는 두 개의 열입니다.
a) A와 B가 모두 null이면 동일하고 거짓이 되세요
b) A와 B가 둘 다 NULL이 아닌 경우 A <> B를 반환합니다.
c) a 또는 b 중 하나가 널이면 같지 않으면 동일하지 않습니다.
해결책
데이터 유형 및 열의 가능한 값에 따라 :
COALESCE(A, -1) <> COALESCE(B, -1)
트릭은 절대 데이터에 나타납니다.
다른 방법은 다음과 같습니다.
(A <> B) OR (A IS NOT NULL AND B IS NULL) OR (A IS NULL AND B IS NOT NULL)
특정 RDBMS가 널을 처리하는 방식에 따라 문제가 될 수 있습니다. ANSI 표준에 의해, 이것은 당신이 원하는 것을 제공해야하지만 어쨌든 표준을 따르는 사람. :)
추신 - 또한 Coalesce 함수를 사용하면 열을 비교할 때 인덱스 사용이 무효화 될 수 있음을 지적해야합니다. 쿼리 계획 및 쿼리 성능을 확인하여 문제가 있는지 확인하십시오.
PPS- 방금 OMG Ponies가 Informix가 Coalesce를 지원하지 않는다고 언급 한 것을 알았습니다. 내가 믿는 ANSI 표준 기능이지만 표준에 대해 위에서 말한 내용을 봅니다 ...
다른 팁
나는 특히 테이블이 커질 것으로 예상되는 경우, 당신이 생각해 낸 표현을 개인적으로 쓸 것입니다. 함수로 열을 랩핑하면 엔진이 해당 열에있는 인덱스를 사용할 수 없도록하여 성능이 상처를 입 힙니다. 물론 작은 테이블에서는 어떤 종류의 문제가 아닐 수도 있지만, 테이블이 성장하는 경우를 대비하여 여전히 명백한 방법으로하고 싶습니다.
Informix에서 이와 같은 것을 시도해 볼 수 있습니까?
CASE
WHEN a IS NULL AND B IS NULL THEN false
WHEN a IS NULL OR B IS NULL THEN true
ELSE a <> B
END
Nulls가 어떻게 처리되는지 확인하려면 Null Checking을 위해 Informix 지원이 무엇이든 사용해야합니다. SE 버전 외에는 Coalesce를 지원하지 않지만 Decode 및 경우를 지원합니다.
WHERE COALESCE(t.a, 0) != COALESCE(t.b, 0)
WHERE DECODE(NULL, 0, t.a) != DECODE(NULL, 0, t.b)
SQL Server의 경우 사용하십시오.
WHERE ISNULL(A, '') <> ISNULL(B, '')
문제는 그게 다 a<>b
(또는 a=b
) 수율 NULL
, 아니다 1
또는 0
하나 또는 둘 다 피연산자가 무인 상태 일 때. 이것은 중요하지 않습니다 =
케이스 NULL OR 1
~이다 1
그리고 NULL OR 0
~이다 NULL
같은 행동 0
a에서 선택하기 위해 WHERE
절.
넌 말할 수있다:
a<>b OR (a IS NULL)<>(b IS NULL)
그러나 어느 쪽이든 그렇게해야한다는 것은 NULL을 잘못 사용한다는 신호일 수 있으며,이 비슷한 조건을 의미하기 위해 다른 널 값이 아닌 다른 값을 사용하도록 스키마를 변경하는 것을 고려해야합니다.
예를 들어, 당신이있는 경우 person
a title
열, null을 사용하여 제목이 없음을 나타냅니다. 그것은 '누락 된'데이텀이 아니라 제목이 없다는 것입니다. 따라서 빈 줄로 보관하십시오 ''
다른 빈 줄과 행복하게 비교할 수 있습니다. (빈 문자열 문제로 Oracle을 실행하지 않으면 ...)
IBM Informix Dynamic Server는 다양한 역사적 (일명 '나쁜'이유에 대한 부울에 대한 다소 독특한 견해를 가지고 있습니다. @astander가 제안한 아이디어를 적응 시키면서이 사례 표현식 'Works', 그러나 나는 '명백하지 않음'이라고 말한 것입니다 (참조 - 나는 당신이하기 전에 그것을 말했습니다!). 설정 단계 :
create table x(a int, b int);
insert into x values(null, null);
insert into x values(null, 1);
insert into x values(1, null);
insert into x values(1, 1);
insert into x values(1, 2);
SELECT 문 :
SELECT *
FROM x
WHERE CASE
WHEN a IS NULL AND b IS NULL THEN 'f'::BOOLEAN
WHEN a IS NULL OR b IS NULL THEN 't'::BOOLEAN
WHEN a != b THEN 't'::BOOLEAN
ELSE 'f'::BOOLEAN
END
;
이 쿼리의 결과는 다음과 같습니다.
1
1
1 2
문제 :
- ID는 거짓 또는 참 또는 미지의 키워드로 인식하지 못합니다.
- IDS는 'a! = b'(또는 'a <> b')와 같은 부울 표현을 인식하지 못합니다.
그렇습니다. 이것을 진술 해야하는 것은 크게 고통 스럽습니다.
만약에
where ((A=B) OR (A IS NULL AND B IS NULL))
평등을위한 것입니다. 그러면 사용하지 않는 이유는 다음과 같습니다.
where NOT (
((A=B) OR (A IS NULL AND B IS NULL))
)
불평등을 위해?