[SQL 코어 파헤치기] NOT IN과 NULL의 치명적 함정 - 3값 논리(Three-Valued Logic)

이성진·2026년 4월 2일

프로그래머스 SQL

목록 보기
7/7

SQL 코딩테스트를 풀다 보면 로직이 완벽함에도 불구하고 결과가 아예 나오지 않는(Empty Set) 현상을 마주할 때가 있다. 특히 서브쿼리와 함께 NOT IN을 사용할 때 이 현상이 자주 발생하는데, 그 원인은 바로 데이터베이스의 3값 논리(Three-Valued Logic)NULL 처리에 있다.

🚨 문제의 상황: IN은 되는데 NOT IN은 왜 안 될까?

-- 1. 정상 작동
WHERE ID IN (SELECT PARENT_ID FROM ECOLI_DATA)

-- 2. 결과가 아예 안 나옴 (Empty Set)
WHERE ID NOT IN (SELECT PARENT_ID FROM ECOLI_DATA)

서브쿼리 결과에 NULL이 포함되어 있을 때, 단지 NOT 하나만 붙였을 뿐인데 모든 데이터가 증발해 버린다. 일반적인 프로그래밍 언어의 2값 논리(True/False)로는 이해하기 힘든 이 현상의 원인을 파헤쳐 보자.

🔍 SQL의 3값 논리 (True, False, Unknown)

SQL에는 참과 거짓 외에 UNKNOWN(알 수 없음) 이라는 상태가 존재한다. NULL이 포함된 비교 연산(예: 1 = NULL, 1 != NULL)은 무조건 UNKNOWN을 반환한다.

1. IN 연산자의 내부 동작 (OR 연산)

IN (1, 2, NULL)은 내부적으로 OR로 풀린다.

  • ID = 1 OR ID = 2 OR ID = NULL
  • TRUE OR FALSE OR UNKNOWN \rightarrow 최종 결과: TRUE
  • 결론: OR 연산은 하나라도 참이면 전체가 참이므로, 일치하는 값이 있다면 NULL이 섞여 있어도 정상적으로 통과한다.

2. NOT IN 연산자의 내부 동작 (AND 연산)

NOT IN (1, 2, NULL)은 내부적으로 AND로 풀린다.

  • ID != 1 AND ID != 2 AND ID != NULL
  • TRUE AND TRUE AND UNKNOWN \rightarrow 최종 결과: UNKNOWN
  • 결론: AND 연산은 모두 참이어야 참이다. 하지만 ID != NULLUNKNOWN을 뱉어내기 때문에, 전체 논리식이 UNKNOWN이 되어버린다. WHERE 절은 오직 TRUE인 행만 통과시키므로, 서브쿼리에 NULL이 단 하나라도 있다면 모든 데이터가 필터링되어 사라진다.

🛠️ 해결 방안: NULL 지뢰 제거

이 함정을 피하는 가장 직관적인 방법은 서브쿼리 내부에서 원천적으로 NULL을 제거하는 것이다.

SELECT ID 
FROM TABLE_A
WHERE ID NOT IN (
    SELECT PARENT_ID 
    FROM ECOLI_DATA 
    WHERE PARENT_ID IS NOT NULL -- NULL 명시적 제거
)

[핵심 요약]
서브쿼리와 함께 NOT IN을 사용할 때는 기계적으로 "서브쿼리 결과에 NULL이 섞여 있지는 않은가?" 를 의심하고 방어 코드를 작성하는 습관을 들이자.

profile
알고리즘과 cs지식 학습

0개의 댓글