소스: sql-src/mid_01_subquery/01_scalar_inline.sql, 02_correlated.sql. 샘플 스키마는 dept(부서), emp(직원)입니다.
SELECT
name
, sal
, (SELECT AVG(sal) FROM emp) AS company_avg
FROM emp
ORDER BY id;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 이 붙습니다. 서브쿼리가 바깥 행과 무관하게 딱 한 번만 계산되는 비상관 스칼라 서브쿼리이기 때문입니다.
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;DEPT | AVG_SAL
-----+--------
경영 | 900.0
개발 | 500.0
지원 | 500.0
영업 | 440.0
인사 | 425.0
(5행)GROUP BY 로 만든 집계 결과를 t 라는 이름의 임시 테이블처럼 다시 걸렀습니다. HAVING avg_sal > 400 도 같은 결과지만, 집계 결과에 다른 테이블(부서명 등)을 조인해야 할 때는 인라인 뷰가 더 편합니다. 집계는 emp 만으로 먼저 끝내고 표시용 컬럼만 나중에 붙이면 조인 비용도 줄어듭니다.
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;NAME | SAL
-------+----
김대표 | 900
이팀장 | 650
정팀장 | 600
서팀장 | 550
(4행)
NAME | DEPT
-------+-----
박선임 | 개발
이팀장 | 개발
최사원 | 개발
김대표 | 경영
문사원 | 인사
서팀장 | 인사
(6행)
NAME | SAL
-------+----
김대표 | 900
이팀장 | 650
(2행)첫 문장은 단일행(전체 평균 하나), 둘째는 IN 다중행(서울 부서 목록), 셋째는 ALL 다중행(영업팀 모든 급여보다 큼)입니다. ALL 은 영업팀 최고 급여(600)보다도 커야 하므로 2명만 남았습니다.
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;NAME | DEPT | SAL
-------+------+----
이팀장 | 개발 | 650
김대표 | 경영 | 900
정팀장 | 영업 | 600
서팀장 | 인사 | 550
강팀장 | 지원 | 500
(5행)바깥 쿼리의 e.dept 를 안쪽 서브쿼리가 참조합니다. 행마다 "내 부서의 최고 급여"를 다시 구해 비교하므로 상관 서브쿼리입니다. 아래 두 쿼리는 같은 결과(위 표와 동일)를 JOIN, 윈도 함수로 재작성한 것입니다.
-- 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 로 부서별 최고 급여를 컬럼에 바로 붙입니다. 반복 실행이 사라지는 편이 많아 데이터가 많을 때 유리합니다.