SQLD2026년 4월 29일· 11 min read· 조회 2

SQLD 서브쿼리 완전 정복 (스칼라·인라인·상관 차이)

SQLD 2과목 서브쿼리 영역에서 헷갈리는 4가지 유형과 EXISTS·IN 차이까지, 매회 출제되는 핵심을 한 글로 정리했습니다.

안녕하세요. 문어입니다 🐙


결론 먼저

SQLD 2과목에서 서브쿼리는 매회 3–4문제 고정으로 나옵니다. 위치별로 이름이 달라지는 게 핵심이고, 거기서 정답이 갈려요.

유형위치특징
스칼라SELECT 절행 1개 + 컬럼 1개만 반환해야 함
인라인 뷰FROM 절가상 테이블처럼 동작, ALIAS 필수
중첩 (Nested)WHERE 절단일행/다중행으로 나뉨
상관 (Correlated)WHERE 절메인 쿼리의 컬럼을 참조, 행마다 재실행

여기에 다중행 연산자(IN, ANY, ALL, EXISTS)와 NOT IN의 NULL 함정까지 합치면 SQLD 서브쿼리 출제 범위가 사실상 다 커버됩니다.


왜 서브쿼리에서 점수가 갈리나

JOIN처럼 그림으로 이해되는 영역이 아니어서 그래요. 위치만 바뀌어도 이름이 바뀌고, 결과 행 수가 안 맞으면 바로 오류가 납니다.

특히 "이 서브쿼리는 몇 행을 반환하는가?" 만 머릿속에 정확히 그려져도 절반은 풀려요. SQLD에서 서브쿼리 문제는 결과 예측 + 함정 인식이 거의 전부입니다.

서브쿼리는 위치(SELECT/FROM/WHERE) → 반환 행 수 → 메인 쿼리 컬럼 참조 여부, 이 3가지 축으로만 정리하면 됩니다.

1. 스칼라 서브쿼리 (SELECT 절)

SELECT 컬럼 자리에 들어가는 서브쿼리. 행 1개 + 컬럼 1개만 반환해야 합니다.

SELECT 사번,
       이름,
       (SELECT 부서명 FROM 부서 d WHERE d.부서코드 = e.부서코드) AS 부서명
  FROM 직원 e;

체크 포인트:

  • 결과가 2행 이상이면 오류 (single-row subquery returns more than one row)
  • 결과가 0행이면 NULL 반환 (오류 X) — 자주 틀리는 부분
  • 결과가 2컬럼 이상이면 오류

JOIN으로 충분히 대체 가능하지만, "이 컬럼 하나만 더 붙이고 싶다" 는 의도를 명확히 드러낼 때 씁니다.


2. 인라인 뷰 (FROM 절)

FROM 자리에 들어가는 서브쿼리. 가상 테이블로 취급되고 ALIAS가 거의 필수예요.

SELECT d.부서명, t.평균급여
  FROM (SELECT 부서코드, AVG(급여) AS 평균급여
          FROM 직원
         GROUP BY 부서코드) t
  JOIN 부서 d ON d.부서코드 = t.부서코드;

체크 포인트:

  • 메인 쿼리의 컬럼 참조 불가 (참조하면 오류)
  • 그룹화한 결과를 다시 조인할 때 가장 많이 씀
  • TOP-N 쿼리(ROWNUM 활용)에서도 단골
SELECT *
  FROM (SELECT * FROM 직원 ORDER BY 급여 DESC)
 WHERE ROWNUM <= 5;

위처럼 인라인 뷰 안에서 정렬 → ROWNUM으로 자르기가 SQLD 출제 단골 패턴입니다.


3. 중첩 서브쿼리 (WHERE 절, 비상관)

WHERE 자리에 들어가고, 메인 쿼리 컬럼을 참조하지 않는 서브쿼리. 한 번 실행 후 결과를 메인 쿼리에서 사용해요.

단일행 서브쿼리

비교 연산자(=, >, <, >=, <=)와 함께. 결과가 2행 이상이면 오류.

SELECT 이름, 급여
  FROM 직원
 WHERE 급여 > (SELECT AVG(급여) FROM 직원);

다중행 서브쿼리

결과가 여러 행일 때 사용하는 연산자:

연산자의미예시
IN결과 집합 중 하나라도 일치WHERE 부서코드 IN (SELECT ...)
ANY, SOME결과 중 하나라도 조건 만족> ANY(...) = 최소값보다 크면 됨
ALL결과 모두 조건 만족> ALL(...) = 최대값보다 커야 함
EXISTS결과 행이 1개라도 있으면 TRUEWHERE EXISTS (SELECT 1 ...)

> ANY vs > ALL은 매번 헷갈리는데, ANY = 가장 작은 값보다, ALL = 가장 큰 값보다 만 외우면 됩니다.


4. 상관 서브쿼리 (Correlated)

WHERE 절 서브쿼리 중에서 메인 쿼리의 컬럼을 참조하는 형태. 메인 쿼리의 행마다 서브쿼리가 다시 실행돼요.

SELECT 이름, 급여
  FROM 직원 e
 WHERE 급여 > (SELECT AVG(급여)
                 FROM 직원
                WHERE 부서코드 = e.부서코드);

→ "각 직원이 자기 부서 평균보다 많이 받는가?" 를 묻는 쿼리입니다.

체크 포인트:

  • 메인 쿼리의 alias(e)를 서브쿼리 안에서 참조
  • 행 수만큼 서브쿼리 반복 실행 → 인덱스 없으면 느려짐
  • SQLD에서는 "실행 횟수" 를 묻는 문제도 가끔 나옴

비상관 서브쿼리는 1번만, 상관 서브쿼리는 메인 쿼리 행 수만큼 실행된다는 점이 핵심.


IN vs EXISTS 차이

비슷해 보이지만 동작 방식이 다릅니다.

-- IN
SELECT 사번 FROM 직원
 WHERE 부서코드 IN (SELECT 부서코드 FROM 부서 WHERE 위치 = '서울');

-- EXISTS (상관 서브쿼리)
SELECT 사번 FROM 직원 e
 WHERE EXISTS (SELECT 1 FROM 부서 d
                 WHERE d.부서코드 = e.부서코드 AND d.위치 = '서울');
항목INEXISTS
서브쿼리 결과값 집합 전체를 반환행 존재 여부만 확인 (TRUE/FALSE)
NULL 처리결과 집합에 NULL 포함 시 함정NULL 영향 없음
성능결과 집합이 작을 때 유리메인 행이 적을 때 유리

→ "NULL 포함 가능성이 있으면 EXISTS" 만 기억하면 시험에서 안전합니다.


NOT IN의 NULL 함정 (매회 단골)

다중행 서브쿼리에서 가장 함정인 부분.

-- 직원 테이블에 NULL 부서코드가 있다면?
SELECT 사번 FROM 외부직원
 WHERE 부서코드 NOT IN (SELECT 부서코드 FROM 부서);
-- → NULL 포함 시 결과가 항상 비어버립니다

NOT IN (..., NULL)은 SQL 3치 논리에서 항상 UNKNOWN이 되어서, 결과적으로 0행 반환돼요. 의도한 결과가 안 나옵니다.

해결법은 두 가지:

-- 방법 1: 서브쿼리에서 NULL 제외
WHERE 부서코드 NOT IN (SELECT 부서코드 FROM 부서 WHERE 부서코드 IS NOT NULL);

-- 방법 2: NOT EXISTS 사용 (권장)
WHERE NOT EXISTS (SELECT 1 FROM 부서 d WHERE d.부서코드 = e.부서코드);
시험에서 NOT IN 보면 NULL 함정 의심 1순위. 이 패턴은 매회 1문제는 무조건 출제됩니다.

NULL 관련 패턴은 SQLD NULL 함정 문제 완전 정복 글에서 더 깊이 다뤘어요.


자주 틀리는 5가지 패턴

1. 스칼라 서브쿼리에서 0행 반환 오류가 아니라 NULL이 반환됩니다. "오류"라고 헷갈리는 보기 자주 나와요.

2. 인라인 뷰에서 메인 컬럼 참조 시도 인라인 뷰는 비상관입니다. 메인 컬럼 참조하면 오류.

3. 단일행 서브쿼리에 다중행 결과 = (SELECT ...)인데 결과가 2행 이상이면 런타임 오류. 비교 연산자 + 다중행은 절대 안 됨.

4. > ANY vs > ALL 혼동

  • > ANY(10, 20, 30)10보다 크면 됨 (가장 작은 값 기준)
  • > ALL(10, 20, 30)30보다 커야 함 (가장 큰 값 기준)

5. NOT IN + NULL → 0행 위에서 설명. 항상 의심.


시험장에서의 접근법

  1. 위치부터 식별: SELECT(스칼라) / FROM(인라인) / WHERE(중첩·상관)
  2. 반환 행 수 확인: 1행 / N행 / 빈 결과
  3. 메인 컬럼 참조 여부: 있으면 상관, 없으면 비상관
  4. NULL이 보이면 NOT IN 가드 의심
  5. > ANY/ALL 나오면 머릿속으로 최소/최대값 대입

이 5단계만 기계적으로 적용하면 서브쿼리 4문제 중 3.5문제는 맞출 수 있어요.

시간이 부족하면 서브쿼리는 우선순위 상위로 풀어두세요. JOIN보다 함정이 정형화되어 있어 점수 회수율이 높습니다.

정리

  • 위치 → 이름 → 동작: 서브쿼리는 위치만 바뀌어도 이름이 바뀜
  • 스칼라: 1행 1컬럼 강제, 0행이면 NULL
  • 인라인 뷰: ALIAS 필수, 메인 컬럼 참조 불가
  • 중첩(비상관): 1번 실행, 다중행이면 IN/ANY/ALL/EXISTS
  • 상관: 메인 행마다 재실행, 컬럼 참조 가능
  • NOT IN + NULL: 항상 0행 → NOT EXISTS로 회피

SQLD 모의고사로 서브쿼리 문제 풀어보기 →


관련 글

직접 문제를 풀어보세요

매번 새로운 모의고사와 무한 풀이 모드로 실전 감각을 키울 수 있습니다.