공공부하자개발 · 영어 학습 노트
SQL
SQL 중급서브쿼리·조인·함수·DDL·인덱스0/11 완료
  • 01서브쿼리: 스칼라·인라인 뷰·상관 서브쿼리, DB별 차이
  • 02EXISTS·IN·NOT IN 과 NULL 함정
  • 03조인 심화: INNER·OUTER·SELF·CROSS, Oracle (+)
  • 04집합 연산: UNION·UNION ALL·INTERSECT·MINUS/EXCEPT
  • 05조건 로직: CASE·DECODE·IIF
  • 06NULL 처리 함수
  • 07문자·날짜 함수 DB별 비교
  • 08DDL 과 제약 조건
  • 09인덱스 기초
  • 10집계와 GROUP BY·HAVING
  • 11뷰·시퀀스·자동 증가
사이트 소개개인정보처리방침연락처
© 2026 공부하자
홈 › SQL 중급 › 01 / 11

서브쿼리: 스칼라·인라인 뷰·상관 서브쿼리, DB별 차이

섹션 6진행 0 / 11
1왜 배우는가2핵심 원리3코드 예제4응용 변형 예제5자주 하는 실수 (Tip)6정리‹ 이전다음 ›

3. 코드 예제

소스: sql-src/mid_01_subquery/01_scalar_inline.sql, 02_correlated.sql. 샘플 스키마는 dept(부서), emp(직원)입니다.

예제 1: 스칼라 서브쿼리로 전체 평균 붙이기

sql
SELECT
       name
     , sal
     , (SELECT AVG(sal) FROM emp) AS company_avg
  FROM emp
 ORDER BY id;
text
NAME   | SAL | COMPANY_AVG
-------+-----+------------
김대표 | 900 | 507.0
이팀장 | 650 | 507.0
박선임 | 500 | 507.0
최사원 | 350 | 507.0
정팀장 | 600 | 507.0
한주임 | 400 | 507.0
(총 10행, 뒤 4행 생략)

모든 행에 같은 값 507.0 이 붙습니다. 서브쿼리가 바깥 행과 무관하게 딱 한 번만 계산되는 비상관 스칼라 서브쿼리이기 때문입니다.

예제 2: 인라인 뷰로 부서 평균 필터링

sql
SELECT
       t.dept
     , t.avg_sal
  FROM (
        SELECT
               dept
             , AVG(sal) AS avg_sal
          FROM emp
         GROUP BY dept
       ) t
 WHERE t.avg_sal > 400
 ORDER BY t.avg_sal DESC;
text
DEPT | AVG_SAL
-----+--------
경영 | 900.0
개발 | 500.0
지원 | 500.0
영업 | 440.0
인사 | 425.0
(5행)

GROUP BY 로 만든 집계 결과를 t 라는 이름의 임시 테이블처럼 다시 걸렀습니다. HAVING avg_sal > 400 도 같은 결과지만, 집계 결과에 다른 테이블(부서명 등)을 조인해야 할 때는 인라인 뷰가 더 편합니다. 집계는 emp 만으로 먼저 끝내고 표시용 컬럼만 나중에 붙이면 조인 비용도 줄어듭니다.

예제 3: WHERE 절 단일행·다중행 서브쿼리

sql
SELECT
       name
     , sal
  FROM emp
 WHERE sal > (SELECT AVG(sal) FROM emp)
 ORDER BY sal DESC;

SELECT
       name
     , dept
  FROM emp
 WHERE dept IN (SELECT code FROM dept WHERE loc = '서울')
 ORDER BY dept, name;

SELECT
       name
     , sal
  FROM emp
 WHERE sal > ALL (SELECT sal FROM emp WHERE dept = '영업')
 ORDER BY sal DESC;
text
NAME   | SAL
-------+----
김대표 | 900
이팀장 | 650
정팀장 | 600
서팀장 | 550
(4행)

NAME   | DEPT
-------+-----
박선임 | 개발
이팀장 | 개발
최사원 | 개발
김대표 | 경영
문사원 | 인사
서팀장 | 인사
(6행)

NAME   | SAL
-------+----
김대표 | 900
이팀장 | 650
(2행)

첫 문장은 단일행(전체 평균 하나), 둘째는 IN 다중행(서울 부서 목록), 셋째는 ALL 다중행(영업팀 모든 급여보다 큼)입니다. ALL 은 영업팀 최고 급여(600)보다도 커야 하므로 2명만 남았습니다.

예제 4: 상관 서브쿼리로 부서별 최고 급여자

sql
SELECT
       e.name
     , e.dept
     , e.sal
  FROM emp e
 WHERE e.sal = (SELECT MAX(sal) FROM emp x WHERE x.dept = e.dept)
 ORDER BY e.dept;
text
NAME   | DEPT | SAL
-------+------+----
이팀장 | 개발 | 650
김대표 | 경영 | 900
정팀장 | 영업 | 600
서팀장 | 인사 | 550
강팀장 | 지원 | 500
(5행)

바깥 쿼리의 e.dept 를 안쪽 서브쿼리가 참조합니다. 행마다 "내 부서의 최고 급여"를 다시 구해 비교하므로 상관 서브쿼리입니다. 아래 두 쿼리는 같은 결과(위 표와 동일)를 JOIN, 윈도 함수로 재작성한 것입니다.

sql
-- JOIN 재작성
SELECT
       e.name
     , e.dept
     , e.sal
  FROM emp e
  JOIN (
        SELECT
               dept
             , MAX(sal) AS max_sal
          FROM emp
         GROUP BY dept
       ) m
    ON m.dept = e.dept AND m.max_sal = e.sal
 ORDER BY e.dept;

-- 윈도 함수 재작성
SELECT
       name
     , dept
     , sal
  FROM (
        SELECT
               name
             , dept
             , sal
             , MAX(sal) OVER (PARTITION BY dept) AS dept_max
          FROM emp
       ) t
 WHERE sal = dept_max
 ORDER BY dept;

두 방식 모두 직접 실행해 위 표와 같은 5행 결과를 확인했습니다. JOIN 재작성은 그룹별 최고 급여를 먼저 구해 원본과 맞춰보고, 윈도 함수 재작성은 PARTITION BY 로 부서별 최고 급여를 컬럼에 바로 붙입니다. 반복 실행이 사라지는 편이 많아 데이터가 많을 때 유리합니다.

예제 직접 실행

아래 폴더의 SQL 파일을 Git Bash 에서 H2 메모리 DB 로 실행합니다. 방언은 파일 안의 SET MODE 로 바꿉니다.

cd sql-src/mid_01_subquery
ls *.sql
bash ../run.sh <파일>.sql
코드 예제
  • 예제 1: 스칼라 서브쿼리로 전체 평균 붙이기
  • 예제 2: 인라인 뷰로 부서 평균 필터링
  • 예제 3: WHERE 절 단일행·다중행 서브쿼리
  • 예제 4: 상관 서브쿼리로 부서별 최고 급여자
이전 섹션2 핵심 원리3 / 6다음 섹션4 응용 변형 예제