쿼리 10-7은 쿼리 10-5에서 사용한 IN 대신 EXISTS 연산자를 사용해 변환한 것으로, 두 쿼리 결과는 동일합니다. EXISTS 연산자는 메인쿼리의 테이블 데이터를 기준으로 서브쿼리에서 반환하는 데이터가 존재하면 참(TRUE)을 반환합니다. 특이한 점은 메인쿼리와 서브쿼리의 조인 조건절을 서브쿼리 내의 WHERE 절에서 기술한다는 점이죠. 또한, EXISTS 연산자는 비교하는 데이터가 존재하는지 여부만을 체크하고, 이 부분은 서브쿼리의 WHERE 절에서 처리하기 때문에 서브쿼리의 SELECT 절에는 굳이 컬럼을 명시하지 않고 아무 값이나 쓰면 됩니다. 여기서는 1을 명시했는데, 0이나 심지어 NULL을 기술해도 됩니다.
다음으로 안티 조인에 대해 알아보겠습니다. 안티 조인은 세미 조인과 형식은 같은데 NOT 연산자가 들어간다는 점이 다릅니다. NOT에 반대라는 의미가 있으므로 안티(anti) 조인이란 이름이 붙은 것입니다. 쿼리 10-5를 안티 조인으로 변경해 보죠.
쿼리 10-8 NOT 연산자를 사용한 안티 조인(쿼리 10-5를 안티 조인으로 변경)
SELECT *
FROM dept_master a
WHERE a.dept_id NOT IN ( SELECT b.dept_id
FROM emp_master b
WHERE b.age BETWEEN 40 AND 49
);
▲ 그림 10-8 쿼리 10-8을 실행한 결과