NOT IN의 NULL 함정

서브쿼리에 NULL이 하나만 있어도 결과가 0행이 될 수 있습니다

핵심은 성능보다 조건의 의미 변화입니다. 같은 "주문 없는 사용자 찾기"라도, NOT IN은 NULL을 제거하지 않으면 모든 비교가 막힐 수 있습니다.

공통 전제

orders.user_id 서브쿼리 결과에 NULL이 섞여 있습니다.

SELECT user_id FROM orders → 101, 205, NULL
비교 축

안전하지 않은 NOT IN

NULL을 그대로 포함한 채 비교

안전한 방법

NULL 제거 또는 NOT EXISTS

쿼리
WHERE u.user_id NOT IN ( SELECT user_id FROM orders )
WHERE u.user_id NOT IN ( SELECT user_id FROM orders WHERE user_id IS NOT NULL ) 또는 WHERE NOT EXISTS (...)
평가 방식
비교가 이렇게 풀립니다
u.user_id <> 101 AND <> 205 AND <> NULL
마지막 비교가 UNKNOWN이 되므로 전체 조건도 TRUE가 되지 못합니다.
의미가 유지됩니다
비교 대상에서 NULL을 제거하거나, 아예 매칭 행의 존재 여부만 확인하므로 안티 조인 의미가 깨지지 않습니다.
최종 결과
실제 반환
아무 행도 반환되지 않을 수 있음
주문이 없는 사용자도 결과에서 사라집니다.
실제 반환
주문이 없는 사용자만 정상 반환
실무 기본값은 보통 NOT EXISTS입니다.
학습 결론

NOT IN의 함정은 "느림"이 아니라 "NULL 때문에 결과 의미가 바뀜"입니다. 그래서 NOT IN을 쓸 때는 서브쿼리에 WHERE user_id IS NOT NULL를 반드시 붙이거나, 더 안전한 NOT EXISTS를 선택합니다.