728x90
-- LNNVL 함수는 condition 이 FALSE 나 UNKNOWN 이면 TRUE, TRUE 이면 FLASE를 반환한다.
-- 출처 : 불친절한 SQL 프로그래밍 P161
SELECT ENAME, COMM
FROM EMP
WHERE LNNVL ( COMM <> 0 ) ;
-- NULL <> 0 -> UNKNOWN -> TRUE
-- 0 <> 0 -> FALSE -> TRUE
-- 1 <> 0 -> TRUE -> FALSE
-- 결국 아래와 같은 의미
SELECT ENAME, COMM
FROM EMP
WHERE ( COMM IS NULL OR COMM = 0 ) ;
-- P 335
-- UNION, INTERSECT, MINUS 연산자는 중복 값을 제거하기위해 데이터 집합을 정렬한다.
-- 대량 데이터의 소트가 발생하면 쿼리 성능이 저하 될 수 있다.
-- INTERSECT, MINU 연산자는 서브 쿼리로의 변경을 통해 소트 발생량을 감소 시킬 수 있다.
DROP TABLE T1 PURGE ;
DROP TABLE T2 PURGE ;
CREATE TABLE T1 ( C1 VARCHAR2(1) NOT NULL, C2 NUMBER ) ;
CREATE TABLE T2 ( C1 VARCHAR2(1) NOT NULL, C2 NUMBER ) ;
INSERT INTO T1 (C1, C2) VALUES ( 'A',1);
INSERT INTO T1 (C1, C2) VALUES ( 'A',2);
INSERT INTO T1 (C1, C2) VALUES ( 'B',1);
INSERT INTO T1 (C1, C2) VALUES ( 'B',2);
INSERT INTO T1 (C1, C2) VALUES ( 'Z',NULL);
INSERT INTO T2 (C1, C2) VALUES ( 'B',1);
INSERT INTO T2 (C1, C2) VALUES ( 'B',1);
INSERT INTO T2 (C1, C2) VALUES ( 'B',2);
INSERT INTO T2 (C1, C2) VALUES ( 'C',2);
INSERT INTO T2 (C1, C2) VALUES ( 'Z',NULL);
COMMIT;
SELECT C1, C2 FROM T1
INTERSECT
SELECT C1, C2 FROM T2
ORDER BY 1,2 ;
SELECT DISTINCT A.C1,A.C2
FROM T1 A
WHERE EXISTS ( SELECT 1
FROM T2 X
WHERE X.C1 = A.C1
AND LNNVL(X.C2 <> A.C2 ))
ORDER BY 1,2 ;
SELECT DISTINCT A.C1,A.C2
FROM T1 A
WHERE EXISTS ( SELECT 1
FROM T2 X
WHERE X.C1 = A.C1
AND ( X.C2 IS NULL OR X.C2 = A.C2 ) )
ORDER BY 1,2 ;
-- 위 3개 쿼리는 모두 동일한 결과
C C2
- ----------
B 1
B 2
Z
-- MINUS 연산자는 NOT EXISTS 조건으로 변경할 수 있다.
-- 서브 쿼리를 사용하면 열이 많을 수록 쿼리가 길어지는 단점이 있따.
SELECT C1, C2 FROM T1
MINUS
SELECT C1, C2 FROM T2 ;
SELECT DISTINCT A.C1, A.C2
FROM T1 A
WHERE NOT EXISTS ( SELECT 1
FROM T2 X
WHERE X.C1 = A.C1
AND LNNVL(X.C2 = A.C2)) ;
SELECT DISTINCT A.C1, A.C2
FROM T1 A
WHERE NOT EXISTS ( SELECT 1
FROM T2 X
WHERE X.C1 = A.C1
AND ( X.C2 IS NULL OR X.C2 = A.C2 ) ) ;
-- 마찬가지로, 위 3개 쿼리는 모두 동일한 결과
C C2
- ----------
A 2
A 1