본문 바로가기
SQL/개념

05. 서브쿼리

by Merware 2023. 5. 3.

01. 서브쿼리 개념

서브쿼리 개념

1. 서브쿼리의 특징

  1. 서브쿼리는 연산자와 같은 비교 또는 조회 대상의 오른쪽에 놓이며 괄호 ()로 묶어서 사용.
  2. 특수한 경우를 제외하고 대부분의 서브쿼리에서 ORDER BY 절을 사용할 수 없음.
  3. 서브쿼리의 SELECT 절에 명시한 열은 메인 쿼리의 비교 대상과 같은 자료형 및 같은 개수로 지정해야 함.
  4. 서브쿼리 결과 행 수는 메인쿼리의 연산자와 호환되어야 함. 예를 들어 단일 연산자일 경우, 서브쿼리 결과는 하나의 값이어야 함.
-- 사원 이름이 JONES인 사원의 급여 출력
SELECT SAL
  FROM EMP
 WHERE ENAME = 'JONES';

-- 서브쿼리를 사용하여 JONES의 급여보다 높은 급여를 받는 사원 정보 출력
SELECT *
  FROM EMP
 WHERE SAL > (SELECT SAL
                FROM EMP
               WHERE ENAME = 'JONES');

2. 단일행 서브쿼리

서브쿼리의 결과가 단일 값일 경우 = 등의 연산자와 함께 사용. 서브쿼리가 단일행을 반환하는 경우에는 = 또는 <>, >, <와 같은 연산자를 사용할 수 있음.

-- 사원 이름이 SCOTT인 사원의 입사일 이전에 입사한 사원들 출력
SELECT *
  FROM EMP
 WHERE HIREDATE < (SELECT HIREDATE
                     FROM EMP
                    WHERE ENAME = 'SCOTT');

-- 평균 급여보다 높은 급여를 받는 20번 부서의 사원 정보 출력
SELECT E.EMPNO, E.ENAME, E.JOB, E.SAL, D.DEPTNO, D.DNAME, D.LOC
  FROM EMP E, DEPT D
 WHERE E.DEPTNO = D.DEPTNO
   AND E.DEPTNO = 20
   AND E.SAL > (SELECT AVG(SAL)
                  FROM EMP);

3. 다중행 서브쿼리

다중행 서브쿼리는 여러 행을 반환할 수 있으며, 이때 IN, ANY, SOME, ALL 연산자와 함께 사용.


02. 연산자

1. IN 연산자

IN 연산자는 서브쿼리 또는 집합에 존재하는 값을 비교할 때 사용.

-- 20번 또는 30번 부서의 사원들 정보 출력
SELECT *
  FROM EMP
 WHERE DEPTNO IN (20, 30);

-- 각 부서별 최고 급여와 동일한 급여를 받는 사원 정보 출력
SELECT *
  FROM EMP
 WHERE SAL IN (SELECT MAX(SAL)
                 FROM EMP
               GROUP BY DEPTNO);

2. ANY, SOME 연산자

ANY 또는 SOME 연산자는 서브쿼리에서 반환되는 집합의 어느 값과도 비교할 수 있을 때 사용.

-- 부서별 최대 급여 중 하나와 동일한 급여를 받는 사원 출력
SELECT *
  FROM EMP
 WHERE SAL = ANY (SELECT MAX(SAL)
                    FROM EMP
                  GROUP BY DEPTNO);

-- 30번 부서에서 가장 적은 급여보다 적은 급여를 받는 사원 정보 출력
SELECT *
  FROM EMP
 WHERE SAL < ANY (SELECT SAL
                    FROM EMP
                   WHERE DEPTNO = 30);

3. ALL 연산자

ALL 연산자는 서브쿼리에서 반환되는 모든 값과 비교하여 조건을 만족하는 경우에만 데이터를 반환.

-- 30번 부서의 모든 급여보다 높은 급여를 받는 사원 출력
SELECT *
  FROM EMP
 WHERE SAL > ALL (SELECT SAL
                    FROM EMP
                   WHERE DEPTNO = 30);

4. EXISTS 연산자

EXISTS는 서브쿼리 결과가 하나라도 존재하면 참으로 판단.

-- 사원이 존재하는 부서 정보 출력
SELECT D.DEPTNO, D.DNAME
  FROM DEPT D
 WHERE EXISTS (SELECT 1
                 FROM EMP E
                WHERE E.DEPTNO = D.DEPTNO);

03. 다중열 서브쿼리

다중열 서브쿼리는 여러 열을 반환하며, 메인 쿼리에서 반환되는 열의 개수와 일치해야 함.

-- 각 부서에서 최고 급여를 받는 사원의 정보 출력
SELECT *
  FROM EMP
 WHERE (DEPTNO, SAL) IN (SELECT DEPTNO, MAX(SAL)
                           FROM EMP
                         GROUP BY DEPTNO);

04. FROM 절에 사용하는 서브쿼리 (인라인 뷰)

서브쿼리를 FROM 절에서 사용하여 임시 테이블처럼 활용할 수 있음. 이를 인라인 뷰라고 함.

-- 부서번호가 10인 사원의 정보와 부서 정보 출력
SELECT E10.EMPNO, E10.ENAME, E10.DEPTNO, D.DNAME, D.LOC
  FROM (SELECT * FROM EMP WHERE DEPTNO = 10) E10,
       DEPT D
 WHERE E10.DEPTNO = D.DEPTNO;

05. WITH 절

WITH 절은 서브쿼리를 미리 정의하여 메인 쿼리에서 여러 번 참조할 수 있도록 함. 가독성과 성능을 향상시킬 수 있음.

WITH
E10 AS (SELECT * FROM EMP WHERE DEPTNO = 10),
D AS (SELECT * FROM DEPT)
SELECT E10.EMPNO, E10.ENAME, E10.DEPTNO, D.DNAME, D.LOC
  FROM E10, D
 WHERE E10.DEPTNO = D.DEPTNO;

06. 스칼라 서브쿼리

스칼라 서브쿼리는 단일 값을 반환하며, SELECT 절, WHERE 절 등에서 사용 가능.

-- 스칼라 서브쿼리를 사용하여 각 사원의 급여 등급과 부서 이름 출력
SELECT EMPNO, ENAME, JOB, SAL,
       (SELECT GRADE
          FROM SALGRADE
         WHERE E.SAL BETWEEN LOSAL AND HISAL) AS SALGRADE,
       DEPTNO,
       (SELECT DNAME
          FROM DEPT
         WHERE E.DEPTNO = DEPT.DEPTNO) AS DNAME
  FROM EMP E;

'SQL > 개념' 카테고리의 다른 글

07. 트랜잭션 제어와 세션(TCL)  (0) 2023.05.09
06. 데이터 조작어(DML)  (0) 2023.05.08
04. 조인  (0) 2023.05.03
03. 다중행 함수와 데이터 그룹화  (0) 2023.05.03
02. 오라클 함수  (0) 2023.05.03