서브쿼리 완벽 정리

스칼라·인라인뷰·중첩 서브쿼리부터 EXISTS vs IN까지 시험 빈출 포인트 총정리

1. 서브쿼리 개념

서브쿼리란?

하나의 SQL문 안에 포함된 또 다른 SQL문을 말한다. 메인쿼리(외부쿼리)가 서브쿼리(내부쿼리)를 포함하는 구조이며, 서브쿼리는 반드시 괄호 ( )로 감싸야 한다. 서브쿼리는 단일행 또는 다중행을 반환할 수 있고, SELECT, FROM, WHERE, HAVING 절 등에서 사용할 수 있다.

서브쿼리 사용 시 주의사항

  • • 서브쿼리는 반드시 괄호로 묶어야 한다
  • • 서브쿼리 내에서는 ORDER BY를 사용할 수 없다 (인라인 뷰 제외)
  • • 단일행 서브쿼리에는 단일행 비교연산자, 다중행 서브쿼리에는 다중행 비교연산자를 사용해야 한다
  • • 서브쿼리가 NULL을 반환하면 메인쿼리 결과에 영향을 줄 수 있다

2. 위치에 따른 분류

서브쿼리 위치별 분류 요약

위치명칭특징
SELECT절스칼라 서브쿼리반드시 단일 값(1행 1열) 반환
FROM절인라인 뷰가상 테이블로 사용, 동적 뷰
WHERE절중첩 서브쿼리조건 필터링에 사용

스칼라 서브쿼리 (SELECT절)

SELECT절에 위치하며 반드시 하나의 행에서 하나의 컬럼 값만 반환해야 한다. 2행 이상 반환 시 에러 발생.

SELECT empno, ename,

(SELECT dname FROM dept

WHERE dept.deptno = emp.deptno) AS dname

FROM emp;

  • • 결과가 없으면 NULL 반환
  • • 2건 이상 반환 시 런타임 에러
  • • 주로 JOIN으로 대체 가능

인라인 뷰 (FROM절)

FROM절에 위치하며 서브쿼리 결과가 가상 테이블(뷰)처럼 사용된다. 동적으로 생성되어 SQL문이 끝나면 사라진다.

SELECT a.ename, a.sal, a.avg_sal

FROM (SELECT ename, sal,

AVG(sal) OVER() AS avg_sal

FROM emp) a

WHERE a.sal > a.avg_sal;

  • • 반드시 별칭(Alias) 지정 필요
  • • ORDER BY 사용 가능 (Top-N 쿼리 등)
  • • 복잡한 쿼리를 단계적으로 작성할 때 유용

중첩 서브쿼리 (WHERE절)

WHERE절에 위치하며 메인쿼리의 조건을 필터링하는 데 사용된다. 가장 일반적인 서브쿼리 형태.

SELECT ename, sal

FROM emp

WHERE deptno = (SELECT deptno

FROM emp

WHERE ename = 'SMITH');

3. 반환 행 수에 따른 분류

단일행 서브쿼리

서브쿼리 결과가 항상 1건 이하를 반환한다. 단일행 비교연산자와 함께 사용한다.

연산자의미
=같다
<> , !=같지 않다
< , <= , > , >=크기 비교

서브쿼리 결과가 2건 이상이면 에러 발생!

다중행 서브쿼리

서브쿼리 결과가 여러 건을 반환한다. 다중행 비교연산자와 함께 사용해야 한다.

연산자의미예시
IN목록 중 하나라도 일치WHERE deptno IN (10, 20)
ANY / SOME하나라도 만족하면 TRUEWHERE sal > ANY (...)
ALL모두 만족해야 TRUEWHERE sal > ALL (...)
EXISTS결과가 1건이라도 있으면 TRUEWHERE EXISTS (서브쿼리)

다중컬럼 서브쿼리

서브쿼리 결과가 여러 컬럼을 동시에 반환한다. 메인쿼리의 조건도 여러 컬럼과 비교.

SELECT ename, deptno, sal

FROM emp

WHERE (deptno, sal) IN

(SELECT deptno, MAX(sal)

FROM emp GROUP BY deptno);

4. 연관 서브쿼리 vs 비연관 서브쿼리

비교

구분비연관 서브쿼리연관 서브쿼리
실행 방식서브쿼리 먼저 실행, 결과를 메인에 전달메인쿼리 행마다 서브쿼리 반복 실행
메인쿼리 참조메인쿼리 컬럼을 참조하지 않음메인쿼리 컬럼을 참조함
독립 실행단독 실행 가능단독 실행 불가
성능1회 실행행 수만큼 반복 (대량 데이터 시 주의)

연관 서브쿼리 예시

메인쿼리의 컬럼을 서브쿼리에서 참조하여 행마다 서브쿼리가 다른 결과를 반환한다.

SELECT ename, sal, deptno

FROM emp e

WHERE sal > (SELECT AVG(sal)

FROM emp

WHERE deptno = e.deptno);

각 사원의 부서별 평균 급여보다 높은 급여를 받는 사원 조회

5. EXISTS vs IN 차이

EXISTS vs IN 비교

구분INEXISTS
동작 방식서브쿼리 결과 목록과 값 비교서브쿼리 결과 존재 여부만 확인
서브쿼리 유형비연관 서브쿼리연관 서브쿼리
NULL 처리NULL과 비교 시 UNKNOWN → 결과에서 제외NULL에 영향받지 않음 (존재 여부만 판단)
성능서브쿼리 결과가 작을 때 유리메인쿼리 결과가 작을 때 유리

NOT IN과 NULL 함정

NOT IN 서브쿼리 결과에 NULL이 포함되면 전체 결과가 공집합이 된다. 이는 SQLD 시험에서 매우 자주 출제되는 함정이다.

-- 서브쿼리 결과: (10, 20, NULL)

SELECT * FROM emp

WHERE deptno NOT IN (10, 20, NULL);

-- 결과: 0건 (공집합!)

NOT IN 대신 NOT EXISTS를 사용하면 NULL 문제를 피할 수 있다.

6. 서브쿼리 → JOIN 변환 패턴

변환 가능한 패턴

서브쿼리JOIN 변환
WHERE col IN (SELECT ...)INNER JOIN (중복 주의)
WHERE EXISTS (SELECT ...)INNER JOIN + DISTINCT 또는 Semi Join
WHERE col NOT IN (SELECT ...)LEFT OUTER JOIN + IS NULL
스칼라 서브쿼리 (SELECT절)LEFT OUTER JOIN

일반적으로 JOIN이 서브쿼리보다 성능이 좋지만, 항상 그런 것은 아니다. 옵티마이저가 자동 변환하는 경우도 있다.

7. 시험 빈출 포인트

자주 출제되는 함정

함정설명
다중행에 = 사용다중행 서브쿼리에 = 연산자 사용 시 에러. IN을 써야 함
NOT IN + NULL서브쿼리 결과에 NULL 포함 시 결과가 공집합
스칼라 다중행스칼라 서브쿼리가 2건 이상 반환 시 에러
ANY vs ALL> ANY(1,2,3) = >1 (최솟값), > ALL(1,2,3) = >3 (최댓값)
연관 vs 비연관서브쿼리가 메인쿼리 컬럼을 참조하면 연관 서브쿼리

ANY / ALL 정리

  • > ANY: 최솟값보다 크면 TRUE (하나라도 만족)
  • < ANY: 최댓값보다 작으면 TRUE
  • > ALL: 최댓값보다 크면 TRUE (모두 만족)
  • < ALL: 최솟값보다 작으면 TRUE
  • = ANY: IN과 동일

개념을 확인했다면 문제로 실력을 검증해보세요