
안녕하세요, 공부하는 감자입니다 🥔
서브쿼리 공부할 때 스칼라, 인라인 뷰, 중첩, 상관… 이름부터 외우려다 포기할 뻔했어요. 그런데 알고 보니 외울 필요가 없더라고요.
서브쿼리가 어느 절에 있는지만 보면 이름이 자동으로 따라옵니다.
| 위치 | 이름 | 핵심 제약 |
|---|---|---|
| SELECT 절 | 스칼라 서브쿼리 | 1행 1컬럼만 반환 가능 |
| FROM 절 | 인라인 뷰 | 가상 테이블, ALIAS 필수 |
| WHERE 절 | 중첩 서브쿼리 | 단일행/다중행 구분 |
| WHERE 절 + 메인 컬럼 참조 | 상관 서브쿼리 | 메인 행마다 재실행 |
SQLD 2과목에서 서브쿼리는 매회 3~4문제 고정 출제인데, 출제 포인트도 정해져 있어요. "이 서브쿼리는 몇 행을 반환하는가"와 "함정을 알아채는가", 사실상 이 둘이 전부입니다.
SELECT 절: 스칼라 서브쿼리
컬럼 자리에 들어가는 서브쿼리예요. 반드시 행 하나, 컬럼 하나만 내놔야 합니다.
SELECT o.order_no,
o.amount,
(SELECT c.cust_name FROM CUSTOMER c
WHERE c.cust_id = o.cust_id) AS cust_name
FROM ORDERS o;
시험 포인트 세 개.
- 결과가 2행 이상 → 실행 오류
- 결과가 0행 → 오류가 아니라 NULL 반환 (여기서 정말 많이 틀려요)
- 컬럼이 2개 이상 → 오류
"0행이면 오류"라는 보기가 함정으로 단골 출제됩니다. 오류 아니고 NULL입니다.
FROM 절: 인라인 뷰
FROM 자리에 들어가면 가상 테이블 취급이에요. 별칭을 붙여서 일반 테이블처럼 조인합니다.
SELECT c.cust_name, t.avg_amt
FROM (SELECT cust_id, AVG(amount) AS avg_amt
FROM ORDERS
GROUP BY cust_id) t
JOIN CUSTOMER c ON c.cust_id = t.cust_id;
기억할 것은 두 가지. 인라인 뷰 안에서는 메인 쿼리의 컬럼을 참조할 수 없다는 것(참조하면 오류), 그리고 TOP-N 패턴의 재료라는 것.
SELECT *
FROM (SELECT * FROM ORDERS ORDER BY amount DESC)
WHERE ROWNUM <= 3;
"인라인 뷰에서 정렬해놓고 바깥에서 ROWNUM으로 자르기" — 이 구조가 SQLD 단골 출제 패턴입니다. ROWNUM을 정렬 전에 매기면 안 되니까 꼭 이 순서여야 해요.
WHERE 절: 단일행이냐 다중행이냐
메인 컬럼을 참조하지 않는 WHERE 절 서브쿼리는 한 번만 실행되고, 그 결과를 메인 쿼리가 받아 씁니다. 이때 결과 행 수에 따라 쓸 수 있는 연산자가 갈려요.
단일행이면 비교 연산자(=, >, < 등)와 같이 씁니다.
SELECT order_no, amount
FROM ORDERS
WHERE amount > (SELECT AVG(amount) FROM ORDERS);
이때 서브쿼리 결과가 2행 이상이면 런타임 오류예요. "비교 연산자 + 다중행 결과 = 오류" 조합을 묻는 문제가 꼭 나옵니다.
다중행이면 전용 연산자를 씁니다.
| 연산자 | 의미 |
|---|---|
| IN | 결과 중 하나라도 일치 |
| ANY (SOME) | 하나라도 조건 만족 → > ANY는 최솟값보다 크면 통과 |
| ALL | 전부 조건 만족 → > ALL은 최댓값보다 커야 통과 |
| EXISTS | 행이 하나라도 있으면 TRUE |
> ANY(10, 20, 30)은 10보다 크면 되고, > ALL(10, 20, 30)은 30보다 커야 합니다.
"ANY는 최소, ALL은 최대"로 외우면 끝.
상관 서브쿼리: 행마다 다시 실행
WHERE 절 서브쿼리인데 메인 쿼리의 별칭을 안에서 참조하면 상관 서브쿼리입니다.
SELECT o.order_no, o.amount
FROM ORDERS o
WHERE o.amount > (SELECT AVG(amount)
FROM ORDERS
WHERE cust_id = o.cust_id);
"각 주문이 그 고객의 평균 주문액보다 큰가?"를 묻는 쿼리예요. 비상관 서브쿼리는 딱 1번 실행되지만, 상관 서브쿼리는 메인 쿼리 행 수만큼 반복 실행됩니다.
SQLD에서 이 "실행 횟수" 차이를 묻기도 해요.
최종 보스: NOT IN + NULL
서브쿼리 영역에서 가장 악명 높은 함정이고, 매회 한 문제는 나온다고 봐도 됩니다.
SELECT c.cust_id FROM CUSTOMER c
WHERE c.cust_id NOT IN (SELECT cust_id FROM BLACKLIST);
-- BLACKLIST.cust_id에 NULL이 하나라도 있으면 → 0행
NULL이 섞인 목록과의 NOT IN 비교는 3치 논리에서 UNKNOWN이 되어 결과가 통째로 비어버립니다. 회피법은 두 가지예요.
-- 서브쿼리에서 NULL 제거
WHERE cust_id NOT IN (SELECT cust_id FROM BLACKLIST
WHERE cust_id IS NOT NULL);
-- 또는 NOT EXISTS (권장)
WHERE NOT EXISTS (SELECT 1 FROM BLACKLIST b
WHERE b.cust_id = c.cust_id);
비슷한 맥락에서 IN과 EXISTS 비교 문제도 나옵니다. IN은 값 집합을 통째로 받아 비교하고, EXISTS는 행 존재 여부(TRUE/FALSE)만 봐요.
NULL의 영향을 받지 않는 쪽은 EXISTS입니다. "NULL 가능성이 있으면 EXISTS"만 기억하면 안전해요.
풀이 루틴 5단계
- 위치 식별 — SELECT/FROM/WHERE 어느 절인가
- 반환 행 수 추정 — 1행인가 N행인가 0행인가
- 메인 컬럼 참조 여부 — 있으면 상관
- NOT IN이 보이면 NULL 의심
- ANY/ALL이 보이면 최솟값/최댓값 대입
이 순서를 기계적으로 돌리면 서브쿼리 문제는 함정이 정형화되어 있어서 점수 회수율이 높습니다. 저는 이 유형만 골라 반복하려고 모의고사를 회차별로 돌렸는데, 그때 쓴 게 문어CBT였어요.
SQLD·정처기·컴활·ADsP 무료 CBT 모의고사
기출 변형 문제, 자동 채점, 회차별 실력 추적까지 가입 없이 바로 풀어보세요.
sqldpass.com
무료인데 해설이 달려 있어서 틀린 서브쿼리 문제 복기할 때 도움이 됐습니다.
위치가 이름이고, 행 수가 정답입니다. 서브쿼리는 이 두 문장으로 요약돼요.
'자격증 > SQLD' 카테고리의 다른 글
| SQLD 독학 3주 공부법, 시간 배분 전략 (0) | 2026.06.30 |
|---|---|
| SQLD 합격 기준과 과락 계산법 (0) | 2026.06.23 |
| SQLD 기출복원 최신 회차 모음 — 58회부터 무료로 풀어보기 (0) | 2026.06.23 |
| SQLD 62회 접수 7/20 시작, 이번 놓치면 11월까지 없어요 (0) | 2026.06.23 |
| SQLD CONNECT BY 계층 쿼리 정리 (PRIOR 이해법) (0) | 2026.06.22 |