이번달 퀴즈는 두가지 부정형 조인 NOT IN, NOT EXISTS 의 차이점을 설명하는것입니다.

문제를 명확히 하기 위해서 아래와 같은 상황을 고려하겠습니다.

테이블 : TEST1

     NO

Name

1

Lee

2

Kim

Park

<NULL>

Jang

<NULL>

<NULL>

 

테이블 : TEST2

NO 

 

Name

 

1

Lee

2

Kim

Park

<NULL>

Jang

* <NULL>은 데이터가 NULL값인 경우입니다.

 

테스트 쿼리

1) NOT IN 의 경우

SELECT *
   FROM TEST1 A
  WHERE A.NO NOT IN (SELECT NO FROM TEST2)

2) NOT EXISTS 의 경우

SELECT *
   FROM TEST1 A
  WHERE NOT EXISTS (SELECT 1 FROM TEST2 B WHERE A.NO = B.NO)

위와 같은 상황에서 두 개의 테스트 쿼리를 실행하여 그 결과에 대해 왜 그렇게 나왔는지 설명하세요.

 

 

답안)

이번달 퀴즈의 문제는 NOT IN과 NOT EXISTS의 차이점이 무엇인가입니다.

 

1번, 2번의 경우에서 NO의 값 1,2,3은 모두 결과에 나오지 않습니다. 즉, TEST2에 속하지 않는것을 찾는것이므로 결과에 나오지 않게됩니다. 차이점은 NULL 값이 결과에 나오는가 아닌가에 있습니다.

 

NOT IN(1번)의 경우

where절의 조건이 맞는지 틀리는지를 찾는것입니다. 그런데 NULL은 조인에 참여하지 않기때문에 결과에서 빠집니다. 여기서 TEST1의 NULL값이 나오지 않은 이유는 IN 서브쿼리의 결과에 NULL유무에 영향을 받지 않습니다. 즉, TEST2의 NO컬럼에 NULL값이 없어도 TEST1의 NO컬럼의 NULL값은 결과에 나오지 않습니다.

 

NOT EXISTS(2번)의 경우

EXISTS는 서브쿼리가 TRUE인지 FALSE인지 체크하는 것이므로  NOT EXISTS는 서브쿼리가 FALSE이면 전체적으로 TRUE가 됩니다. 서브쿼리에서 TEST1과 TEST2의 조인시 NULL은 결과에서 빠지게 됩니다. 이것은 서브쿼리를 FALSE로 만들게 되고 전체적으로 TRUE가 되어 TEST1의 NULL값이 결과에 나오게 됩니다.

 

이번 퀴즈는 매우 쉬운것 같으나 자칫 잘못 생각할 수 있는 내용이기 때문에 퀴즈로 다루었습니다. 일반적으로 대용량을 처리할 때 성능상의 이유로 Hash Anti-Join, Merge Anti-Join으로 유도하기 위해 NOT EXISTS를 NOT IN으로 바꿔서 처리하기도 합니다. 이때 두 부정형 조인의 결과가 같다는 전제 조건이 있어야 합니다. 그러나 위에서와 같이 연결고리가 되는 컬럼의 값 중 NULL이 포함된 경우 결과가 다르다는것을 주의해야 합니다.


+ Recent posts