상관 EXISTS와 NOT EXISTS
NULL을 올바르게 처리하는 견고한 안티 조인 대안을 알아봅니다.
상관 EXISTS와 NOT EXISTS은(는) CoddyKit의 무료 Coding Interview Prep 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Coding Interview Prep 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Coding Interview Prep 강의에는 총 4개의 강의가 포함되어 있습니다.
EXISTS는 존재 여부를 검사합니다
EXISTS는 서브쿼리를 받아 해당 서브쿼리가 하나 이상의 행을 반환하는 즉시 TRUE를 반환하고, 그렇지 않으면 FALSE를 반환합니다. 행 자체를 반환하지는 않습니다.
상관 서브쿼리와 함께 사용하면 EXISTS는 외부 행마다 존재 여부를 검사합니다. 즉, "이 외부 행에 대응하는 행이 존재하는가?"를 확인합니다.
첫 번째 일치 항목을 찾는 즉시 검사를 중단하므로 몇 개의 행이 일치하는지는 중요하지 않습니다. 이런 의미상의 세부 사항은 면접에서 자주 다뤄지는 핵심 포인트입니다.
기본적인 상관 EXISTS
주문을 한 번 이상 넣은 고객을 찾으십시오. 내부 쿼리는 o.customer_id = c.customer_id를 통해 상관 관계를 가집니다.
각 고객에 대해 EXISTS는 이 고객의 주문이 하나라도 있는지 묻습니다. 있으면 해당 고객을 남깁니다.
SELECT c.customer_id, c.name
FROM customers c
WHERE EXISTS (
SELECT 1
FROM orders o
WHERE o.customer_id = c.customer_id
);EXISTS 안에서 SELECT 1을 사용하는 이유
EXISTS 안에서 SELECT 1, SELECT *, SELECT NULL을 보게 될 것입니다. 세 표현은 모두 같은 의미입니다.
EXISTS는 행이 반환되는지만 확인하고 행의 내용은 확인하지 않으므로, 선택되는 열은 중요하지 않습니다. 최적화기는 이 열들을 무시합니다.
SELECT 1은 의도를 나타내는 일반적인 관례입니다. 즉, "존재 여부만 관심 있습니다."라는 뜻입니다. 하나를 선택해 일관되게 사용하십시오. 여기서 열 목록이 중요하다고 면접관이 오해하게 만들지는 마십시오.
NOT EXISTS로 누락된 항목 찾기
NOT EXISTS는 검사를 반대로 합니다. 상관 서브쿼리가 어떤 행도 반환하지 않을 때만 외부 행을 남깁니다.
이는 전형적인 반조인입니다. 주문이 없는 고객, 한 번도 판매되지 않은 상품, 제출물이 없는 학생을 찾을 때 사용합니다.
SELECT c.customer_id, c.name
FROM customers c
WHERE NOT EXISTS (
SELECT 1
FROM orders o
WHERE o.customer_id = c.customer_id
);NOT IN과 NULL의 함정
면접에서 반드시 알아야 할 핵심 내용입니다. NULL을 포함할 수 있는 서브쿼리에 NOT IN을 사용하면 위험하게 동작합니다. 목록에 NULL이 하나라도 있으면 NOT IN은 어떤 행도 반환하지 않습니다.
NULL과 비교한 결과는 UNKNOWN이 되고, NOT IN은 모든 비교 결과가 거짓이어야 하기 때문에 이런 일이 발생합니다. UNKNOWN 하나가 전체 조건을 무효화합니다.
NOT EXISTS에는 이런 문제가 없습니다. 단순히 행의 존재 여부를 확인하므로 NULL도 안전하게 처리합니다.
-- Risky: returns nothing if any o.customer_id is NULL
SELECT c.customer_id FROM customers c
WHERE c.customer_id NOT IN (SELECT o.customer_id FROM orders o);
-- Safe: NULLs do not break it
SELECT c.customer_id FROM customers c
WHERE NOT EXISTS (
SELECT 1 FROM orders o WHERE o.customer_id = c.customer_id
);NOT EXISTS가 NULL에 안전한 이유
그 이유는 일치 여부를 판단하는 방식에 있습니다. NOT EXISTS는 내부 행 중 o.customer_id = c.customer_id를 만족하는 행이 있는지 확인합니다.
o.customer_id가 NULL인 행은 해당 등식(NULL = anything은 TRUE가 아니라 UNKNOWN입니다)을 절대로 만족하지 못하므로 일치하는 행으로 계산되지 않습니다. 따라서 존재 여부 검사는 올바르게 유지됩니다.
NOT IN에서는 같은 NULL이 목록 비교의 일부가 되고, 그 결과인 UNKNOWN이 모든 출력 결과를 없애 버립니다. 이것이 경력자 면접에서 NOT EXISTS를 선호하는 이유입니다.
EXISTS의 추가 조건
상관 서브쿼리에는 조건식을 더 포함할 수 있습니다. 1000을 초과하는 주문을 하나 이상 한 고객을 찾습니다.
추가 조건은 고객별 범위가 적용되는 EXISTS 서브쿼리 내부에 둡니다.
SELECT c.customer_id, c.name
FROM customers c
WHERE EXISTS (
SELECT 1
FROM orders o
WHERE o.customer_id = c.customer_id
AND o.amount > 1000
);성능: 단락 평가 동작
EXISTS는 일치하는 행 하나를 찾는 즉시 내부 관계의 검색을 중단할 수 있습니다. 전체 결과 집합을 만들거나 개수를 세지 않습니다.
따라서 EXISTS는 일반적으로 효율적이며, 특히 상관 열에 인덱스가 있으면 각 행별 탐색에서 일치 항목을 빠르게 찾아 조기에 종료할 수 있습니다.
모든 일치 항목을 세어야 하는 상관 COUNT(*) > 0과 대조해 보십시오. 예/아니요로 존재 여부만 확인하면 될 때는 EXISTS를 선호하십시오.
존재 여부를 위한 EXISTS와 COUNT
지원자는 존재 여부를 검사하기 위해 상관 COUNT를 작성하는 경우가 있습니다. 작동하지만 불필요한 작업을 합니다.
COUNT 방식은 일치하는 모든 주문의 개수를 세지만, EXISTS는 첫 번째 항목에서 종료합니다. 순수한 존재 여부 검사라면 EXISTS가 의도를 명확하게 전달하고 최적화기가 단락 평가를 수행할 수 있게 합니다.
-- Works but counts everything
SELECT c.customer_id FROM customers c
WHERE (SELECT COUNT(*) FROM orders o
WHERE o.customer_id = c.customer_id) > 0;
-- Better: stops at first match
SELECT c.customer_id FROM customers c
WHERE EXISTS (SELECT 1 FROM orders o
WHERE o.customer_id = c.customer_id);풀이 예제: 한 번도 주문되지 않은 제품
전형적인 안티 조인 면접 문제는 한 번도 주문되지 않은 제품을 나열하는 것입니다. NOT EXISTS는 영어로 된 요구 사항을 거의 그대로 표현합니다.
각 제품에 대해 어떤 주문 항목이 해당 제품을 참조하는지 확인하고, 그런 항목이 없는 제품만 남깁니다.
SELECT p.product_id, p.name
FROM products p
WHERE NOT EXISTS (
SELECT 1
FROM order_items oi
WHERE oi.product_id = p.product_id
);나눗셈 유형 쿼리에서의 EXISTS와 NOT EXISTS
NOT EXISTS 안에 EXISTS를 중첩하면 관계형 나눗셈을 표현할 수 있습니다. 즉, "집합의 모든 항목과 일치하는 행을 찾는 것"입니다. 전형적인 문제는 "카테고리의 모든 제품을 주문한 고객"을 찾는 것입니다.
논리는 다음과 같습니다. 주문하지 않은 제품이 하나도 없는 고객만 남깁니다. 이 이중 부정은 나눗셈 쿼리의 대표적인 특징이며, 면접관은 이를 통해 EXISTS 활용 능력을 심도 있게 검사합니다.
SELECT c.customer_id
FROM customers c
WHERE NOT EXISTS (
SELECT 1 FROM products p
WHERE p.category = 'Coffee'
AND NOT EXISTS (
SELECT 1 FROM order_items oi
JOIN orders o ON o.order_id = oi.order_id
WHERE oi.product_id = p.product_id
AND o.customer_id = c.customer_id
)
);빠른 확인
주문이 없는 고객을 찾는 가장 안전한 방법을 선택하십시오.
요약: 상관 EXISTS와 NOT EXISTS
핵심 내용:
EXISTS는 첫 번째 일치 항목에서 단락 평가를 수행하는 행별 존재 여부 검사입니다. 내부에서 어떤 열을 선택하는지는 중요하지 않으므로SELECT 1을 사용하십시오.NOT EXISTS는 일치 항목이 없는 행을 찾을 때 NULL에도 안전한 안티 조인입니다.- 목록에 NULL이 포함된
NOT IN은 아무것도 반환하지 않으므로NOT EXISTS를 선호하십시오. - 존재 여부를 확인할 때 EXISTS는 상관
COUNT(*) > 0보다 효율적입니다. 더 일찍 중단하기 때문입니다.
질문받지 않아도 NOT IN의 NULL 함정을 언급하십시오. 이는 SQL 숙련도를 확실하게 보여 주는 신호입니다.
자주 묻는 질문
“상관 EXISTS와 NOT EXISTS” 강의는 무료인가요?
네 — “상관 EXISTS와 NOT EXISTS” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Coding Interview Prep 강의 전체를 잠금 해제할 수 있습니다. Coding Interview Prep 강의에는 총 4개의 강의가 포함되어 있습니다.
“상관 EXISTS와 NOT EXISTS”에서 뭘 배우나요?
NULL을 올바르게 처리하는 견고한 안티 조인 대안을 알아봅니다. 브라우저에서 직접 실행하는 실습 코드로 Coding Interview Prep을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Coding Interview Prep을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Coding Interview Prep은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.
“상관 EXISTS와 NOT EXISTS” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Coding Interview Prep 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Coding Interview Prep 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- 상관 하위 쿼리의 구조
- GROUP BY 없이 그룹별 집계하기
- 상관 EXISTS와 NOT EXISTS
- 상관 하위 쿼리를 JOIN으로 다시 작성하기