[SQL] 서브쿼리(Subquery)란? 상관서브쿼리 / 스칼라와 인라인뷰 / 단일행과 다중행 서브쿼리 / 서브쿼리와 메인쿼리 참조
by 우와한개발자
1. 서브쿼리란?
- 서브쿼리란 하나의 SQL문 안에 포함된 또 다른 SQL문
- 메인 쿼리가 실행되기 전에 서브쿼리가 먼저 실행되고, 그 결과를 메인 쿼리가 사용
- 메인쿼리 : 서브쿼리를 감싸고 있는 바깥쪽 쿼리 (외부쿼리)
2. 참조에 따른 서브쿼리의 종류
1) 연관 서브쿼리 Correlated Subquery
- 외부 쿼리의 컬럼을 참조하는 서브쿼리
- 외부쿼리의 각 행마다 서브쿼리가 된다
- 반복 실행
SELECT 이름, 부서, 급여
FROM 직원 e1
WHERE 급여 > (
SELECT AVG(급여)
FROM 직원 e2
WHERE e2.부서 = e1.부서 -- 외부 참조
);
2) 비연관 서브쿼리 Independent Subquery
- 외부 쿼리와 독립적으로 실행되는 서브쿼리
- 서브쿼리가 먼저 1번만 실행되고, 그결과를 메인쿼리가 사용
- 옵티마이저가 1번만 실행하도록 최적화함
SELECT 이름, 급여
FROM 직원
WHERE 급여 > (SELECT AVG(급여) FROM 직원);
3. 반환 행 수에 따른 서브쿼리 종류
1) 단일 행 서브쿼리 Single Row Subquery
- 1개이하의 행만 반환하는 서브쿼리
- 비교 연산자(=, >, <, >=, <=, !=)와 함께 사용
- 컬럼의 갯수가 왼쪽항과 같아야함.
연산자 의미 서브쿼리 컬럼 개수 = 같다 1개 또는 여러 개(튜플 가능) > 크다 ❗ 1개만 가능 < 작다 ❗ 1개만 가능 >= 크거나 같다 ❗ 1개만 가능 <= 작거나 같다 ❗ 1개만 가능 <> 또는 != 같지 않다 ❗ 1개만 가능 BETWEEN 범위 ❗ 1개만 가능 LIKE 패턴 검색 ❗ 1개만 가능 IS NULL NULL 여부 ❗ 1개만 가능
SELECT 이름
FROM 직원
WHERE 급여 = (SELECT MAX(급여) FROM 직원);
2) 다중 행 서브쿼리 Multiple Row Subquery
- 여러 행을 반환하는 서브쿼리
- 다중행 비교 연산자(IN, ANY, ALL, EXISTS)와 함께 사용
- EXISTS를 제외하고 컬럼의 갯수는 왼쪽과 같아야함.연산자 의미 컬럼 개수
IN 여러 값 중 하나 ⭕ 여러 컬럼 가능 NOT IN 여러 값 모두와 다름 ⭕ 여러 컬럼 가능 ANY 하나라도 만족 ❗ 1개만 가능 ALL 모두 만족 ❗ 1개만 가능 EXISTS 반환되는 행이 있는지 하나라도 있는지 컬럼 개수 상관 없음
SELECT 이름
FROM 직원
WHERE 부서 IN (SELECT 부서명 FROM 부서 WHERE 지역 = '서울');
SELECT 이름
FROM 직원
WHERE 급여 < ANY (300, 400, 500)
SELECT 이름
FROM 직원
WHERE 급여 > ALL (SELECT 급여 FROM 직원 WHERE 부서 = 'IT');
SELECT 고객명
FROM 고객 c
WHERE EXISTS ( SELECT 1 FROM 주문 o WHERE o.고객ID = c.고객ID);
4. 위치에 따른 서브쿼리 종류
1) 스칼라 서브쿼리 Scalar Subquery : SELECT 절
- SELECT 절에 오는 서브쿼리
- 단일행 반환
- (연관 스칼라 경우) 메인 쿼리의 각 행마다 서브쿼리가 실행.
- 서브쿼리의 별칭/컬럼을 외부 쿼리가 참조 불가
-- 연관 스칼라 : 각 행마다 결과가 달라져 외부쿼리 행만큼 실행
SELECT 이름, 부서, 급여,
(SELECT AVG(급여)
FROM 직원 e2
WHERE e2.부서 = e1.부서) as 부서평균
FROM 직원 e1;
-- 비연관 스칼라 : 옵티마이저가 1번만 실행
SELECT 이름, 급여,
(SELECT AVG(급여) FROM 직원) as 전체평균
FROM 직원;
2) 인라인 뷰 Inline View : FROM 절
- FROM 절에 오는 서브쿼리
- 서브쿼리를 임시 테이블처럼 사용
- 서브쿼리의 별칭/컬럼을 외부 쿼리가 참조가능
SELECT sub.부서, sub.평균급여
FROM (
SELECT 부서, AVG(급여) as 평균급여
FROM 직원
GROUPBY 부서
) sub;
3) WHERE 절
- 서브쿼리 결과의 값만 사용
- 서브쿼리의 별칭/컬럼을 외부 쿼리가 참조불가.
SELECT 이름
FROM 직원
WHERE 급여 > (SELECT AVG(급여) FROM 직원);
4) HAVING, ORDER BY절
SELECT 부서, AVG(급여) as 평균급여
FROM 직원
GROUP BY 부서
HAVING AVG(급여) > (SELECT AVG(급여) FROM 직원);
서브쿼리는 외부쿼리의 컬럼/별칭을 사용가능하다.
| 구분 | 서브쿼리 → 외부쿼리 | 외부쿼리 → 서브쿼리 참조 |
| 연관 서브쿼리 | ⭕ 가능 | ❌ 불가 |
| 비연관 서브쿼리 | ❌ 불가 | ❌ 불가 |
| 스칼라 서브쿼리 (SELECT절) | ⭕ 가능 (연관일 때) | ❌ 불가 |
| 인라인 뷰 (FROM절) | ❌ 불가 | ⭕ 가능 (별칭/컬럼 참조 가능) |
| WHERE절 서브쿼리 | ⭕ 가능 (연관일 때) | ❌ 불가 |
| HAVING절 서브쿼리 | ⭕ 가능 (연관일 때) | ❌ 불가 |
'데이터베이스 > SQL' 카테고리의 다른 글
| [SQL] Oracle 계층형 쿼리(Hierarchical Query) 문법 정리 - START WITH / CONNECT BY / PRIOR (0) | 2026.03.24 |
|---|---|
| [SQL] TOP-N 쿼리란? ROWNUM 3중 쿼리 vs OFFSET/FETCH (0) | 2026.03.24 |
| [SQL] Oracle 전용 JOIN 문법 - EQUI / SELF / NON-EQUI / OUTER JOIN (0) | 2026.03.23 |
| [SQL] 조인(JOIN)이란? – INNER / NATURAL / CROSS / OUTER JOIN과 예시 (0) | 2026.03.23 |
| [SQL] 피벗 테이블 – 롱/와이드 포맷, OLTP/OLAP, PIVOT/UNPIVOT (0) | 2026.03.23 |
블로그의 정보
우와한개발자 님의 블로그
우와한개발자