데이터베이스/Oracle

SQL문 속 또 다른 SQL문, 서브쿼리

eunsour 2020. 7. 29.
반응형

DBMS - Oracle Database

VERSION - Oracle Database 11g Release 2

IDE - SQL Developer

 

실습용 데이터를 입력하지 않고, 오라클 데이터베이스를 설치하면 기본으로 제공되는 테이블과 계정들로 학습한 내용입니다. 


※ 서브쿼리

1. 서브쿼리란?

서브쿼리(Subquery)는 SQL문을 실행하는 데 필요한 데이터를 추가로 조회하기 위해 SQL문 내부에서 사용하는 SELECT문을 의미한다.

SELECT * FROM EMP
    WHERE SAL > (SELECT SAL 
                    FROM EMP
                    WHERE ENAME = 'JONES');

결과 >>

'JONES'의 급여보다 높은 급여를 받는 사원 정보 출력하기

# 서브쿼리의 특징

 

  1.  서브쿼리는 연산자와 같은 비교 또는 조회 대상의 오른쪽에 놓이며 괄호 ( )로 묶어서 사용한다.
  2. 특수한 몇몇 경우를 제외한 대부분의 서브쿼리에서는 ORDER BY절을 사용할 수 없다.
  3. 서브쿼리의 SELECT절에 명시한 열은 메인쿼리의 비교 대상과 같은 자료형과 같은 갯수로 지정해야 한다. 즉 메인쿼리의 비교 대상 데이터가 하나라면 서브쿼리의 SELECT절 역시 같은 자료형인 열을 하나 지정해야 한다.
  4. 서브쿼리에 있는 SELECT문의 결과 행 수는 함께 사용하는 메인쿼리의 연산자 종류의 호환 가능해야 한다. 예를 들어 메인쿼리에 사용한 연산자가 단 하나의 데이터로만 연산이 가능한 연산자라면 서브쿼리의 결과 행 수는 반드시 하나여야 한다.

※ 실행 결과가 하나인 단일행 서브쿼리

:  실행 결과가 단 하나의 행으로 나오는 서브쿼리

단일행 연산자
> >= = <= < <> ^= !=
초과 이상 같은 이하 미만 같지 않음

 

1. 단일행 서브쿼리와 날짜형 데이터

SELECT * FROM EMP
    WHERE HIREDATE < (SELECT HIREDATE
                        FROM EMP
                        WHERE ENAME = 'JAMES');

결과 >> 

EMP 테이블에서 JAMES보다 빨리 입사한 사원 목록을 조회

 

2. 단일형 서브쿼리와 함수

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);

결과 >>

20번 부서에 속한 사원 중 전체 사원의 평균 급여보다 높은 급여를 받는 사원 정보와 소속 부서 정보를 함께 조회


※ 실행 결과가 여러 개인 다중행 서브쿼리

:  실행 결과 행이 여러 개로 나오는 서브쿼리

다중행 연산자 설명
IN 메인쿼리의 데이터가 서브쿼리의 결과 중 하나라도 일치한 데이터가 있다면 true
ANY, SOME 메인쿼리의 조건식을 만족하는 서브쿼리의 결과가 하나 이상이면 true
ALL 메인쿼리의 조건식을 서브쿼리의 결과 모두가 만족하면 true
EXISTS 서브쿼리의 결과가 존재하면(즉, 행이 1개 이상일 경우) true

1. IN 연산자

SELECT * FROM EMP
    WHERE SAL IN (SELECT MAX(SAL)
                    FROM EMP
                    GROUP BY DEPTNO);

 

2. ANY, SOME 연산자

:  서브쿼리가 반환한 여러 결과 값 중 메인쿼리와 조건식을 사용한 결과가 하나라도 true라면 메인쿼리 조건식을 true로 반환해 주는 연산자이다.

SELECT * FROM EMP
    WHERE SAL < ANY (SELECT SAL
                        FROM EMP
                        WHERE DEPTNO = 30)
    ORDER BY SAL, EMPNO;

결과 >>

30번 부서 사원들의 최대 급여보다 적은 급여를 받는 사원 정보 출력하기

 

3. ALL 연산자

:  ANY, SOME과 달리 서브쿼리의 모든 결과가 조건식에 맞아떨어져야만 메인쿼리의 조건식이 true가 되는 연산자이다.

SELECT * FROM EMP
    WHERE SAL < ALL (SELECT SAL
                        FROM EMP
                        WHERE DEPTNO = 30);

결과 >> ANY 연산자를 사용했을 때와는 다른 결과 출력

부서 번호가 30번인 사원들의 최소 급여보다 더 적은 급여를 받는 사원 출력하기

ALL 연산자가 의미하는 것과 같이 서브쿼리의 모든 결과 값(950, 1250, 1500, 1600, 2850)보다 작은 값을 가진 메인쿼리의 행만 true가 되어 출력된다. 

 

4. EXISTS 연산자

:  서브쿼리에 결과 값이 하나 이상 존재하면 조건식이 모두 true, 존재하지 않으면 모두 false가 되는 연산자이다.

SELECT * FROM EMP
    WHERE EXISTS (SELECT DNAME 
                    FROM DEPT
                    WHERE DEPTNO = 10);

결과 >>

서브쿼리 결과 값이 존재하는 경우

SELECT * FROM EMP
    WHERE EXISTS (SELECT DNAME 
                    FROM DEPT
                    WHERE DEPTNO = 50);

결과 >>

서브쿼리 결과 값이 존재하지 않는 경우

EXIST 연산자는 다른 다중행 연산자에 비해 그리 자주 사용하는 편은 아니지만, 특정 서브쿼리 결과 값의 존재 유무를 통해 메인쿼리의 데이터 노출 여부를 결정해야 할 때 간혹 사용한다.

※ 비교할 열이 여러 개인 다중열 서브쿼리

:  서브쿼리의 SELECT절에 비교할 데이터를 여러 개 지정하는 방식 (= 복수열 서브쿼리라고도 부른다.)

SELECT * FROM EMP
    WHERE (DEPTNO, SAL) IN (SELECT DEPTNO, MAX(SAL)
                                FROM EMP
                                GROUP BY DEPTNO);

결과 >>


※ SELECT절에 사용하는 서브쿼리

:  흔히 스칼라 서브쿼리(scalar subquery)라고 부르는 이 서브쿼리는 SELECT절에 하나의 열 영역으로서 결과를 출력할 수 있다.

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;

결과 >>

SELECT절에 명시하는 서브쿼리는 반드시 하나의 결과만 반환하도록 작성해 주어야 한다.

 

 

 

 

Reference

 
Do it! 오라클로 배우는 데이터베이스 입문
저자 : 이지훈
출판 : 이지스퍼블리싱
발매 : 2018.10.30

 

반응형

댓글