IT/SQLD

[SQL] (NOT)EXISTS 와 (NOT)IN 비교하기

알콩달콩아빠 2023. 10. 22. 15:48
728x90
반응형

최근 작업하고 있는 모듈에서 A 테이블과 B 테이블을 비교하여 B 테이블에 없는 값을 A 테이블에서 가져오는 작업을 진행하고 있다. 처음에는 NOT IN 구문을 사용하여 비교하고 가져오고 있었는데, NOT EXISTS 를 사용하면 더 효과적이라는 말을 듣고, 궁금증에 여기저기 검색해보았다. 결론적으로 말하자면 조회 건수가 많지 않은 쿼리에서는 성능이 비슷하지만, 조회 건수가 급격하게 늘어나면 (NOT)EXISTS 구문이 훨씬 효과적이라는 것이다.

초기 데이터

테이블은 rel1 , rel2 테이블을 생성하였다.

rel1

rel2

 

1. (NOT) IN

SELECT * FROM rel1
WHERE number IN (SELECT number FROM rel2);


SELECT * FROM rel1
WHERE number NOT IN (SELECT number FROM rel2);

 

 

IN 구문에서는 가장 먼저 서브쿼리(위에서는 rel2) 를 실행하여 number 요소들을 가져온다.
그 다음에는 메인쿼리의 rel1 에서 row를 하나를 가져오고,
서브쿼리의 row들과 메인쿼리의 row 를 비교하여 같은 것만 반환하게 된다.
위의 과정을 메인쿼리의 row 개수만큼 반복하여 비교한다.

IN 구문은 서브쿼리와 메인쿼리의 값 중 하나라도 일치하면 반환해주지만, NOT IN 쿼리는 모든 요소들과 일치하지 않는 값을 체크하여 반환해주게 된다. 여기서 NULL 값은 DB에서 비교연산을 할 때 항상 UNKNOWN(FALSE) 값을 반환하기 때문에 NULL 이 존재하면 아무 결과도 확인할 수 없다. 원하는 값을 보려면 NULL을 제외하고 조회하면 된다.(WHERE number IS NOT NULL)

 

 

2. (NOT) EXISTS

SELECT * FROM rel1 t1
WHERE EXISTS (SELECT 1 FROM rel2 t2 WHERE t1.number = t2.number);



SELECT * FROM rel1 t1
WHERE NOT EXISTS (SELECT 1 FROM rel2 t2 WHERE t1.number = t2.number);

 

 

EXISTS 구문에서는 IN 구문과 달리 메인쿼리에 먼저 접근하여 row 를 하나 가져오고 EXISTS 의 서브쿼리를 실행시켜
결과가 존재하는지를 판단한다. 서브쿼리의 결과가 TRUE 인지 FALSE 인지 체크하기 떄문에 EXISTS 에서는 TRUE 면
메인쿼리의 결과를 출력하고, NOT EXISTS 에서는 서브쿼리 내 결과가 FALSE 면 메인쿼리의 결과를 출력한다.
여기서 주의할 부분은, 서브쿼리에서 TRUE만 되면 레코드가 출력되기 때문에 두 테이블에서 같은 값을 가져오려면
WHERE 절로 조건을 주어야한다.

NOT EXISTS 에서는 서브쿼리의 결과가 FALSE 면 반환되게 된다. 서브쿼리에서 rel1 과 rel2 의 조인 시 NULL은 위에 IN 에서 설명한 것처럼 비교연산에서 빠지게 되며, 이는 서브쿼리를 FALSE 로 만들고, TRUE가 되어서 NULL 값이 같이 빠져나오게 된다. 그러므로 IN 에서는 나오지 않은 NULL 값이 NOT EXISTS 에서는 나오는 것을 확인할 수 있다.

 

출처 : [SQL] (NOT)EXISTS 와 (NOT)IN 비교하기 (tistory.com)

728x90
반응형

'IT > SQLD' 카테고리의 다른 글

[MSSQL] 트랜잭션 로그 보기  (0) 2023.10.23
[MS-SQL] IN / NOT IN  (0) 2023.10.22
WHERE : 단일 조건식 지정  (0) 2023.10.22
MSSQL DELETE 데이터 삭제하기  (0) 2023.10.22
[ANSI SQL] 7. WHERE 절의 조합(AND / OR / NOT / IN)  (0) 2023.10.22