들어가며
https://school.programmers.co.kr/learn/courses/30/lessons/157339
프로그래머스
SW개발자를 위한 평가, 교육의 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프
programmers.co.kr
해당 문제를 풀면서 IN으로 쿼리문을 작성했을 땐 오답이었지만 EXISTS으로 작성하면 정답으로 나와 둘의 차이를 확실히 알아야겠다고 생각했습니다.
IN vs EXISTS
IN
IN은 해당 열의 값들이 오른쪽 집합(또는 서브쿼리)에 '포함'이 되는지 검사
EXISTS
EXISTS는 서브쿼리가 한 행이라도 존재하면 TRUE가 되는 '존재성'을 체크
따라서 EXISTS를 사용할 땐, 값이 있기만 하면 되고 값 자체는 상관이 없습니다.
예를 들어,
CUSTOMERS 스키마
| customer_id | VARCHAR |
| name | VARCHAR |
ORDERS 스키마
| order_id | VARCHAR |
| customer_id | VARCHAR |
| order_date | DATE |
| amount | INTEGER |
두 테이블을 활용하여 '주문한 적 있는 고객'을 찾고 싶다면
--IN
SELECT *
FROM customers c
WHERE c.customer_id IN (
SELECT o.customer_id
FROM orders o
);
--EXISTS
SELECT *
FROM customers c
WHERE EXISTS (
SELECT 1
FROM orders o
WHERE o.customer_id = c.customer_id
);
두 쿼리문은 답이 똑같이 나오지만 EXISTS가 인덱스를 탐색하게되어 속도적으로 더 빠릅니다!
만약 중복된 customer_id를 지워주고자 한다면 IN은 DISTINCT를 같이 사용해주어야 하지만, EXISTS는 있는지 아닌지를 체크하기 때문에 중복을 제거해주는 DISTINCT는 의미가 없습니다!
예시를 통해 더 알아보겠습니다.
CUSTOMERS 테이블
| customer_id | name | city |
| 1 | Aria | Seoul |
| 2 | Ben | Busan |
| 3 | Cleo | Incheon |
| 4 | Dae | Daegu |
| 5 | Eun | Daejeon |
| 6 | Finn | Gwangju |
ORDERS 테이블
| order_id | customer_id | order_date | amount |
| 101 | 1 | 2025-09-01 | 50 |
| 102 | 1 | 2025-09-09 | 70 |
| 103 | 2 | 2025-09-15 | 120 |
| 104 | 4 | 2025-09-18 | 30 |
| 105 | 4 | 2025-10-01 | 200 |
| 106 | 2025-10-02 | 999 |
EXISTS의 서브쿼리가 실행되는 경우를 예시로 보자면
EXISTS (SELECT 1 FROM orders WHERE o.customer_id = 1(c.customer_id가 1인 경우)
| 1 |
| 1 |
customer_id가 1인 경우가 2번이나 있기에 1이 두 번 생성된 테이블이 생성이 됩니다.
EXISTS의 조건으로 한 행이라도 있기 때문에 customer_id가 1인 경우는 TRUE가 되어 출력이 됩니다.
c.customer_id가 2인 경우와 4인 경우도 똑같이 한 행이라도 있기에 TRUE가 되어 출력이 됩니다.
하지만 3, 5, 6인 경우는 한 행이라도 생성이 되지 않기에 출력이 되지 않습니다.
NOT IN vs NOT EXISTS
NOT을 붙여 사용할 땐 꼭 주의해야할 점이 있습니다.
IN은 집합이나 서브쿼리에 NULL값이 하나라도 섞여있다면 전부 UNKNOWN이 되어 빈 결과가 출력되기 때문에, 부정 조건일 땐 NOT EXISTS를 사용하는 것이 오답을 줄일 수 있는 습관이라고 생각합니다!
'STUDY' 카테고리의 다른 글
| <SQL> SELECT와 비트연산자 이해하기 - [Programmers] 언어별 개발자 분류하기 (0) | 2025.10.14 |
|---|---|
| <SQL> ORDER BY 이해하기 - [Programmers] 노선별 평균 역 사이 거리 조회하기 (0) | 2025.10.12 |
| <SQL> MAX 함수 이해하기 - [Programmers] 자동차 대여 기록에서 대여중 / 대여 가능 여부 구분하기 (0) | 2025.10.08 |
| 티스토리 글 검색 포털에 노출시키기 (0) | 2025.09.25 |
| <Tableau> 커스텀 도형 사용하기 (0) | 2025.09.24 |
