Oracle/Oh Oracle

LNNVL 함수

darkturtle26 2022. 12. 14. 21:31

-- 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