본문 바로가기

RDB

SQL - [NOT] IN과 [NOT] EXISTS의 차이

1. EXISTS : 단순히 EXISTS 절의 결과 존재 유무만으로 T/F 반환 

메인 쿼리 EXISTS(서브 쿼리) :  서브 쿼리의 결과가 " 한 건이라도 존재하면"  TRUE 없으면 FALSE를 리턴한다.

먼저 메인쿼리에 접근하여 하나의 레코드를 가져오고 그 레코드에 대해서 EXISTS 이하의 서브쿼리를 실행하고 서브쿼리에 대한 결과가 '존재하는지'를 확인한다.

EXISTS는 서브 쿼리에 일치하는 결과가 한 건이라도 있으면 쿼리를 더 이상 수행하지 않는다.

IN은 서브쿼리 결과를 모두 수행하고, EXISTS는 일치하는 결과가 있으면 더 이상 수행하지 않는다(반대로 EXISTS는 메인쿼리의 레코드는 모두 순회한다)

서브 쿼리 테이블(dept_history)에 데이터량이 많으면 EXISTS를 사용하는것이 성능이 좋다(메인쿼리에 먼저 접근하기 때문)

EXISTS의 서브 쿼리를 메인 쿼리 JOIN으로 변경할 경우 위와 같이 중복된 데이터 나올 수 있으니 주의해야 한다.

JOIN을 사용하는것이 성능상 좋을 수 있으나 메인 쿼리와 서브 쿼리의 데이터가 1:1일 경우 가능하다.

 

2. IN : 레코드가 IN 절의 결과 리스트와 동일한 값을 가지는지로 T/F 반환

메인 쿼리 IN(서브 쿼리) :  서브 쿼리의 결과 리스트가 메인 쿼리 레코드와 " 동일한 값을 가지는면"  TRUE 없으면 FALSE를 리턴한다.

메인쿼리에 먼저 접근하여, 컬럼값들을 가져와 리스트로 IN 이하에 뿌려주고, 그 이후에 서브쿼리에서 하나의 레코드씩 IN 이하의 요소들과 일치하는지 비교한다

IN 뒤에 있는 괄호의 서브쿼리를 먼저 실행해서 그에 대한 요소를 가져온다(IN뒤에 괄호안에는 서브쿼리 이외에도 직접 요소값을 적어줄 수 있다)

메인 쿼리에서 하나의 레코드를 가져오며 그 레코드의 값이 앞에서 가져온 IN 이하의 요소들에 포함되어 있는지를 체크한다

그리고 IN 이하의 요소들 중 하나라도 일치한다면 그 레코드를 출력

 

3. NOT EXISTS

먼저 메인쿼리에서 레코드를 가져오고 해당 레코드의 컬럼을 NOT EXISTS 이하의 서브쿼리에 전달하여 해당 서브쿼리에서 값이 존재하는지를 확인한다(만약 서브쿼리가 조건절없이 무조건 결과값을 가지는 쿼리라면 NOT EXISTS는 모두 F가 되어 아무값도 출력 되지 않는다)

EXISTS 구문이었다면 값이 존재할 때 해당 레코드를 출력하지만, NOT EXISTS 구문이기에 해당 서브쿼리의 값이 존재하지 않으면 해당 레코드를 출력한다

NOT IN과 같이 NULL에 대한 비교연산은 항상 UNKNOWN 값을 반환하므로 해당 쿼리의 결과가 존재하지 않게 되고, 이에 따라서 레코드가 출력된다.

 

4. NOT IN

NOT IN안의 서브퀘리가 모두 리스트로 연산 되고 나면 메인쿼리에서 하나의 레코드씩 가져올 것이고 IN이 아니라 NOT IN 구문이기 때문에 요소들과 일치하지 않아야 결과로 반환된다.

메인쿼리의 레코드들 중에서 서브쿼리에 요소에 대해서 모두(AND 조건) 일치 하지 않는 조건을 만족할때 T를 반환

즉, NOT IN 구문은 메인에서 가져온 레코드의 값이 서브쿼리의 모든 요소들과 일치하지 않는지를 체크하는 것이다.

NULL값이 포함된 컬럼이라면,  NULL과의 비교연산은 항상 UNKNOWN 값을 반환하게 된다. 따라서 WHERE 절 이하가 TRUE가 아니므로 해당 레코드가 출력되지 않게 된다

 

5. IN과 EXISTS의 차이점

1. 성능

  • EXISTS : 조건에 해당하는 ROW의 존재 유무와 체크 후 더이상 수행 하지 않음 일반적으로 IN에 비해 수행시간이 짧기 때문에 성능이 좋다
  • IN : 조건에 해당하는 ROW의 칼럼을 비교하여 체크한다. IN 조건절에서 조회한 칼럼 값의 모든 요소를 비교하므로 EXISTS에 비해 성능이 떨어진다

2. 동작순서

  • EXISTS : 메인쿼리의 결과값을 서브쿼리에 대입하여 조건비교 후 결과를 출력 (메인 -> 서브)
  • IN : 서브쿼리의 결과값을 메인쿼리에 대입하여 조건 비교 후 결과를 출력 (서브 -> 메인)

3. NULL처리

ORACLE과 MYSQL 등등 결과가 상이

데이터 손실을 막기위해 NULL 컬럼를 전처리 해야한다

출처: https://doorbw.tistory.com/222 gent.tistory.com/278 m.blog.naver.com/mk1126sj/220985926185

'RDB' 카테고리의 다른 글

SQL - JOIN 이해하기  (0) 2020.10.23