NOT EXISTS의 동작 원리

강찬우·2024년 6월 18일

sql

목록 보기
1/3

SQL에서 NOT EXISTS의 동작 원리: 서브쿼리의 반복 실행 이해하기

SQL 쿼리를 작성하다 보면 NOT EXISTS를 사용하여 특정 조건을 만족하지 않는 행을 필터링하는 경우가 많다. NOT EXISTS는 마치 프로그래밍 언어의 for 루프처럼 외부 쿼리의 각 행에 대해 서브쿼리를 반복적으로 실행한다. 이 글에서는 NOT EXISTS의 동작 원리와 이를 활용하는 방법, 그리고 IN, NOT IN, EXISTS, NOT EXISTS의 차이점과 장단점에 대해 자세히 설명한다.

NOT EXISTS란 무엇인가?

NOT EXISTS는 서브쿼리가 한 행이라도 결과를 반환하지 않는 경우 참이 되는 조건문이다. 이는 특정 조건을 만족하지 않는 행을 선택하는 데 유용하다. NOT EXISTS를 사용할 때, SQL 엔진은 외부 쿼리의 각 행에 대해 서브쿼리를 실행하여 조건을 평가한다.

예제 데이터베이스 설정

예제 테이블을 설정하고 데이터를 삽입해 보자. 다음과 같은 두 개의 테이블이 있다고 가정한다: item_infoitem_tree.

CREATE TABLE item_info (
    item_id INT PRIMARY KEY,
    item_name VARCHAR(50)
);

CREATE TABLE item_tree (
    item_id INT,
    parent_item_id INT
);

INSERT INTO item_info (item_id, item_name) VALUES
(1, 'Item A'),
(2, 'Item B'),
(3, 'Item C');

INSERT INTO item_tree (item_id, parent_item_id) VALUES
(1, 2),
(2, 3),
(3, NULL),
(4, 1);

NOT EXISTS 사용 예제

다음 쿼리는 item_info 테이블에서 item_treeparent_item_id로 참조되지 않는 항목들을 선택한다.

SELECT * FROM item_info
WHERE NOT EXISTS (
    SELECT 1 FROM item_tree
    WHERE item_tree.parent_item_id = item_info.item_id
);

동작 원리

위 쿼리는 item_info 테이블의 각 행에 대해 다음과 같은 과정을 거친다.

  1. 첫 번째 행 (item_id = 1):

    • 서브쿼리: SELECT 1 FROM item_tree WHERE item_tree.parent_item_id = 1
    • item_tree 테이블에서 parent_item_id = 1인 행이 존재하므로, 서브쿼리는 결과를 반환한다.
    • NOT EXISTS 조건은 거짓이 되므로, 이 행은 최종 결과에서 제외된다.
  2. 두 번째 행 (item_id = 2):

    • 서브쿼리: SELECT 1 FROM item_tree WHERE item_tree.parent_item_id = 2
    • item_tree 테이블에서 parent_item_id = 2인 행이 존재하므로, 서브쿼리는 결과를 반환한다.
    • NOT EXISTS 조건은 거짓이 되므로, 이 행은 최종 결과에서 제외된다.
  3. 세 번째 행 (item_id = 3):

    • 서브쿼리: SELECT 1 FROM item_tree WHERE item_tree.parent_item_id = 3
    • item_tree 테이블에서 parent_item_id = 3인 행이 존재하지 않으므로, 서브쿼리는 결과를 반환하지 않는다.
    • NOT EXISTS 조건은 참이 되므로, 이 행은 최종 결과에 포함된다.

이와 같은 방식으로 NOT EXISTS는 외부 쿼리의 각 행에 대해 서브쿼리를 반복적으로 실행하여 조건을 평가한다.

IN, NOT IN, EXISTS, NOT EXISTS의 차이점과 장단점

SQL에서는 다양한 방법으로 서브쿼리를 사용할 수 있다. 그 중에서 IN, NOT IN, EXISTS, NOT EXISTS의 차이점과 장단점을 살펴보자.

INEXISTS

IN은 서브쿼리가 반환한 결과 집합에 외부 쿼리의 값이 존재하는지 확인한다. 반면 EXISTS는 서브쿼리가 결과를 반환하는지 여부를 확인한다.

예제:

-- `IN` 사용 예
SELECT * FROM item_info
WHERE item_id IN (
    SELECT parent_item_id FROM item_tree
);

-- `EXISTS` 사용 예
SELECT * FROM item_info
WHERE EXISTS (
    SELECT 1 FROM item_tree
    WHERE item_tree.parent_item_id = item_info.item_id
);

장단점:

  • IN은 서브쿼리의 결과를 메모리에 로드하여 비교하기 때문에 작은 결과 집합에 유리하다.
  • EXISTS는 서브쿼리가 조건을 만족하는 첫 번째 행을 찾으면 즉시 종료되므로, 큰 결과 집합에 유리하다.

NOT INNOT EXISTS

NOT IN은 서브쿼리가 반환한 결과 집합에 외부 쿼리의 값이 존재하지 않는지 확인한다. NOT EXISTS는 서브쿼리가 결과를 반환하지 않는지 여부를 확인한다.

예제:

-- `NOT IN` 사용 예
SELECT * FROM item_info
WHERE item_id NOT IN (
    SELECT parent_item_id FROM item_tree
);

-- `NOT EXISTS` 사용 예
SELECT * FROM item_info
WHERE NOT EXISTS (
    SELECT 1 FROM item_tree
    WHERE item_tree.parent_item_id = item_info.item_id
);

장단점:

  • NOT IN은 서브쿼리의 결과에 NULL 값이 포함되면 의도치 않은 결과를 초래할 수 있다.
  • NOT EXISTS는 서브쿼리가 결과를 반환하지 않는 경우만 참이 되므로 NULL 값을 안전하게 처리할 수 있다.

결론

SQL에서 NOT EXISTS는 매우 강력한 도구다. 이를 사용하여 특정 조건을 만족하지 않는 행을 쉽게 필터링할 수 있다. 외부 쿼리의 각 행에 대해 서브쿼리를 반복적으로 실행하는 방식으로 동작하므로, 마치 프로그래밍 언어의 for 루프처럼 생각할 수 있다. 또한, IN, NOT IN, EXISTS, NOT EXISTS의 차이점과 장단점을 이해하면 상황에 맞는 최적의 쿼리를 작성할 수 있다.

0개의 댓글