[SQL] EXISTS, NOT EXISTS 의 JOIN 교체

SQL 쿼리에서 EXITS 와 NOT EXISTS 구문과 이를 JOIN 으로 대체하는 방법에 대해 정리하겠다.

DataBase 관련 콘텐츠 – 옐로우의 세계



1. EXISTS 구문

(1) 특징

  • 서브쿼리 결과가 존재하는지만 판단
  • 첫 번째 행이 발견되면 바로 TRUE 반환 (효율적)
  • 메인 쿼리와 서브쿼리 간의 상관 관계가 있음 (Correlation subquery)

(2) 예시

SELECT e.emp_id, e.name
FROM employees e
WHERE EXISTS (
  SELECT 1
  FROM departments d
  WHERE d.dept_id = e.dept_id
  AND d.location = 'SEOUL'
);

(3) 장점

  • 조건 충족 여부만 판단할 때 명확하고 간결
  • 서브쿼리에 인덱스가 잘 설정되면 빠르게 TRUE 확인 가능
  • 조건식 기반 필터링에 적합

(4) 단점

  • 옵티마이저 최적화 범위가 좁음 (단순 존재 확인만)
  • 대량 데이터에선 성능 저하 가능
  • 상관 서브쿼리는 반복 실행될 수 있어 비용 증가 가능성


2. INNER JOIN 구문

(1) EXISTS 대체 방식

SELECT e.emp_id, e.name
FROM employees e
JOIN departments d ON e.dept_id = d.dept_id
WHERE d.location = 'SEOUL';

(2) 장점

  • 옵티마이저가 다양한 조인 전략(HASH, NESTED, MERGE 등) 선택 가능
  • 인덱스를 활용한 효율적인 조인 가능
  • 명확하게 어떤 데이터가 결합되는지 확인 가능 (디버깅/튜닝 편리)

(3) 단점

  • 불필요한 컬럼까지 결합되면 메모리 사용량 증가 가능
  • 데이터 중복 결과 조심해야 함



1. NOT EXISTS 구문

(1) 특징

  • 서브쿼리에 해당 조건을 만족하는 행이 없을 때만 TRUE 반환
  • Anti-join과 유사한 로직

(2) 예시

SELECT e.emp_id, e.name
FROM employees e
WHERE NOT EXISTS (
  SELECT 1
  FROM resignations r
  WHERE r.emp_id = e.emp_id
);

(3) 장점

  • 직관적이고 단순한 구조
  • 인덱스를 잘 쓰면 성능 우수
  • Null-safe (null이 포함된 조건도 정확히 처리)

(4) 단점

  • 서브쿼리 반복 실행 가능성
  • 옵티마이저 최적화 여지가 적음

 

2. LEFT JOIN + IS NULL 대체

(1) NOT EXISTS 대체 방식

SELECT e.emp_id, e.name
FROM employees e
LEFT JOIN resignations r ON r.emp_id = e.emp_id
WHERE r.emp_id IS NULL;

(2) 장점

  • 옵티마이저가 Anti-Join 전략(NOT EXISTS)으로 자동 변환하기도 함
  • 조인 방식 선택 가능 (HASH, MERGE 등)
  • 실무에서는 NOT EXISTS 보다 더 유연한 조정 가능

(3) 단점

  • LEFT JOIN 결과에 따라 불필요한 null 포함 가능성
  • IS NULL 조건이 누락되면 의도와 다른 결과 발생



구분EXITSINNER JOINNOT EXISTSLEFT JOIN + IS NULL
용도존재 확인실데이터 조인존재하지 않음 확인존재하지 않음 확인
성능적은 데이터에 효율적대량 데이터에 효율적단순 조건에 적합옵티마이저 활용 유리
인덱스 활용제한적적극 활용 가능제한적인덱스 활용 가능
가독성간결관계가 명확간결조건 누락시 주의 필요
단점옵티마이저 최적화 제한중복, 과조인 주의느릴 수 있음NULL 처리 주의 필요
추천 시점존재 여부만 중요할 때성능이 중요할 때정확한 배제 조건 필요할 때동일 결과를 JOIN으로 표현하고자 할 때



  • 실제 데이터와 실행 계획(EXPLAIN PLAN)을 보고 판단하세요.
  • JOIN으로 바꿨다고 항상 빨라지지는 않습니다.
  • 결과가 달라질 수 있으니, 테스트는 필수입니다.
  • 옵티마이저 힌트와 함께 사용하는 것도 고려해 보세요. (예: /+ USE_NL /, /+ HASH_JOIN /)

[SQL] EXISTS, NOT EXISTS 의 JOIN 교체

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.

Scroll to top