Sub Query (서브 질의)

  • 하나의 SQL문에 중첩된 SELECT문
  • 서브 질의는 주 질의 이전에 한 번 실행됨
  • 서브 질의의 결과는 주 질의에 의해 사용됨


  • 유형 : return 값이 어떤 유형인지
    • 단일 행(Single Row)
    • 다중 행(Multiple Rows)
    • 다중 열(Multiple Columns)


단일 행 서브 질의

  • 하나의 행 반환
  • 단일 행 연산자 =, >, >=, <, <=, <>, !=만 사용 가능
  • 비용이 적게 들어 효율적


  • ex) ‘SMITH’와 같은 job을 갖는 사원 이름, 사원 번호, 업무 출력
      SELECT ename, empno, job
      FROM emp
      WHERE job = (SELECT job
                   FROM emp
                   WHERE ename = 'SMITH');
    
    • 서브 질의 -> ‘SMITH’의 job 반환
    • 서브 질의 결과 SMITH의 job사원들의 job 비교
      IMG_D68E7AB5E202-1


  • cf) Self Join은 비용이 큼 (메모리 많이 사용)
      SELECT e2.ename, e2.job
      FROM emp e1, emp e2
      WHERE e1.ename = 'SMITH'
      and e1.job = e2.job;
    


다중 행 서브 질의

  • 하나 이상의 행을 반환하는 서브 질의
  • 복수 행 연산자 IN, NOT IN, ANY, ALL, EXISTS 사용 가능


  • ex1) 부서별로 가장 급여를 많이 받는 사원 정보
      SELECT empno, ename, sal, deptno
      FROM emp
      WHERE (deptno, sal)
          IN (SELECT deptno, MAX(sql)
              FROM emp
              GROUP BY deptno);
    
    EMPNO ENAME SAL DEPTNO
    7698 BLAKE 2850 30
    7788 SCOTT 3000 20
    7902 FORD 3000 20
    7839 KING 5000 10
    • 다중열 - 다중행
    • 👀 (deptno, sal) : emp의 (deptno, sal) 중 서브 질의 결과와 일치하는 것!
    • 서브 질의 결과: 부서별 MAX(sal)의 empno, sal 반환
    DEPTNO MAX(SAL)
    30 2850
    20 3000
    10 5000


  • ex2) 30번 부서의 최소 급여를 받는 사원보다 많은 급여를 받는 사원의 사원 번호, 사원 이름, 급여, 업무 출력 (30번 부서 제외)
      SELECT empno, ename, sal, job
      FROM emp
      WHERE deptno != 30
      and sal > ANY (SELECT sal
                     FROM emp
                     WHERE deptno = 30);
      -- MIN(sal)로 단일행 비교도 가능
    
    EMPNO ENAME SAL JOB
    7566 JONES 2975 MANAGER
    7782 CLARK 2450 MANAGER
    7788 SCOTT 3000 ANALYST
    7839 KING 5000 PRESIDENT
    7876 ADAMS 1100 CLERK
    7902 FORD 3000 ANALYST
    7934 MILLER 1300 CLERK
    • 👀 ANY : 서브 질의 결과 중 어느 하나라도 -> 최소 급여와 비교하게 됨
    • 👀 ALL 로 바꾼다면 -> 30번 부서의 최고 급여를 받는 사원보다 많은 급여를 받는 사원 출력!
    • 서브 질의 결과 : 30번 부서의 급여들 모두 출력


다중 열 서브 질의

  • 서브 질의 결과값이 두 개 이상의 컬럼을 반환


  • ex1) 급여와 보너스가 부서 30에 있는 어떤 사원의 보너스와 급여에 일치하는 사원의 사원 번호, 사원 이름, 급여, 보너스 출력
      SELECT empno, ename, sal, comm
      FROM emp
      WHERE (sal, NVL(comm, -1))
          IN (SELECT sal, NVL(comm, -1)
              FROM emp
              WHERE deptno = 30);
    
    EMPNO ENAME SAL COMM
    7499 ALLEN 1600 300
    7521 WARD 1250 500
    7654 MARTIN 1250 1400
    7698 BLAKE 2850  
    7844 TURNER 1500 0
    7900 JAMES 950  
    • 다중행 & 다중열 서브 질의
    • 👀 NVL : comm 값이 NULL이면 -1로 대치

      • NULL값도 연산이 가능하게끔!
      • NULL값을 그냥 두면 연산 안하고 건너뜀
        -> NULL이 있는 행은 출력되지 않음
    • 👀 IN : ‘어떤’ -> 서브 질의 결과들 중 일치하는 행이 있다면 출력


  • ex2) 업무별로 최소 급여를 받는 사원의 사원 번호, 이름, 업무, 부서 번호 출력
      SELECT empno, ename, job, deptno
      FROM emp
      WHERE (job, sal)
          IN (SELECT job, MIN(sal)
              FROM emp
              GROUP BY job);
    
    EMPNO ENAME SAL DEPTNO
    7788 SCOTT 3000 20
    7902 FORD 3000 20
    7369 SMITH 800 20
    7782 CLARK 2450 10
    7839 KING 5000 10
    7521 WARD 1250 30
    7654 MARTIN 1250 30