■ 서브쿼리란?


서브쿼리는 쿼리 안에 있는 쿼리문이다. 쿼리란 SELECT문을 참조할 때 사용한다. SELECT문이란 테이블에서 정보를 가져오기 위해 사용한다.

요약을 하자면, 테이블에서 정보를 가져오기 위해 SELCT문을 사용해서 또 다른 SELECT문을 참조한다고 풀이할 수 있다.


-- ALLEN의 직무와 같은 사람의 이름, 부서명, 급여, 직무를 출력하라.


-- JONES 가 속해있는 부서의 모든 사람의 사원번호, 이름, 입사일, 급여를 출력하라.


-- 전체 사원의 평균 임금보다 많은 사원의 사원번호, 이름, 부서명, 입사일, 지역, 급여를 출력하라.


공통점은 어떤 결과와 컬럼을 비교하기 위해 사용한다. 이러한 문제들은 서브쿼리문을 사용하지 않으면 문제를 해결 할 수 없다.



■ 서브쿼리 프로세스


-- FIRST_NAME이 STEVEN인 사원과 같은 부서에서 일을 하는 모든 사원들의 정보


이러한 문제가 있다고 가정을 해보자. 그럼 우선 아래와 같은 과정을 통해 문제를 해결하면 도움이 될 것이다.


1. 어떤 정보를 보고싶은가?

2. 정보가 어디 테이블에 있는가?

3. 조건은 무엇인가? 


우리는 모든 사원들의 정보를 보고싶다. 그 다음 이러한 정보가 어디 테이블에 있는지 알아보니 EMPLOYEES라는 테이블에 있다. 마지막으로 이름이 Steven이라는 사원과 같은 부서에 근무해야 하는 조건에 만족해야 한다.


<Steven이라는 사원과 같은 부서를 조회할 때 문제직면>

1
2
3
4
5
6
SELECT   *
 
FROM     EMPLOYEES
 
WHERE    DEPARTMENT_ID = ?????
;
cs



Steven과 같은 사람의 부서를 비교를 해야하는데 서브쿼리를 모른다면 문제를 해결 할 수 없다. 그렇다면 Steven의 부서를 출력하는 문을 적어보자


<Steven이라는 사람의 부서번호 출력하는 SELECT문>

1
2
3
4
5
6
SELECT    DEPARTMENT_ID
 
FROM      EMPLOYEES
 
WHERE     FIRST_NAME = 'Steven'
;
cs


<출력결과>

출력결과 보니깐 두개가 나왔다. 그렇다면 동명인이 존재하는 것이다. 이런 상황에서 서브쿼리를 사용해보자. ???? 된 곳에 괄호를 쳐서 Steven의 부서를 출력하는 SELECT문을 넣으면 서브쿼리가 완성된다.


<서브 쿼리문>

1
2
3
4
5
6
7
8
SELECT  *
FROM    EMPLOYEES
WHERE   DEPARTMENT_ID = (
                            SELECT  DEPARTMENT_ID
                            FROM    EMPLOYEES
                            WHERE   FIRST_NAME = 'Steven'
                        )
;
cs

<출력문>


에러문이 나왔다. 그 이유는 동명인이 존재하기 때문이다. 서브쿼리문 안에는 출력결과는 2개가 나오는데 어떤 Steven을 말하는지 모르겠다. 라고 말하는 것이다.

<FIRST_NAME이 STEVEN인 사원과 같은 부서에서 일을 하는 모든 사원들의 정보 서브쿼리>

1
2
3
4
5
6
7
8
9
SELECT  *
FROM    EMPLOYEES
WHERE   DEPARTMENT_ID IN (
                            SELECT  DEPARTMENT_ID
                            FROM    EMPLOYEES
                            WHERE   FIRST_NAME = 'Steven'
                        )
;
 
cs

'='은 한 개의 데이터와 비교 할 때 쓰이기 때문에 'IN'을 사용하면 여러 개의 데이터와 비교할 수 있어서 문제를 해결 할 수 있다.

추가적으로 서브쿼리문에서는 공백을 사용하면 안된다. 주의하자.


그렇다면 위에 문제를 응용해서 Steven은 제외한다 라는 조건이 더 붙으면 어떻게 작성해야 할까?


<Steven은 제외한다 라는 조건이 추가>

1
2
3
4
5
6
7
8
9
SELECT  *
FROM    EMPLOYEES
WHERE   DEPARTMENT_ID IN (
                            SELECT  DEPARTMENT_ID
                            FROM    EMPLOYEES
                            WHERE   FIRST_NAME = 'Steven'
                        )
AND     FIRST_NAME !='Steven'
;
cs



◆ IN vs '='


<IN 사용>

1
2
3
4
5
SELECT  *
 
FROM    EMPLOYEES
WHERE   DEPARTMENT_ID IN (1020)
;
cs

<'=' 사용>

1
2
3
4
5
6
SELECT  *
FROM    EMPLOYEES
WHERE   DEPARTMENT_ID = 10
OR        DEPARTMENT_ID = 20
;
 
cs

두 SELECT문은 같은 결과를 출력하지만 속도측면에서 '='를 쓴 SELECT문이 더 빠르다. 상황에 맞게 사용하면 될 것이다.
IN과 '=' 차이점은 간단하다. '='는 한 개의 데이터와 비교하는 할 때 쓰인다. IN을 사용할 때는 1개 이상 데이터와 비교할 때 사용한다.
하지만, 속도 측면에서 IN은 상대적으로 비효율적이기 때문에 1개 데이터를 비교할 때는 꼭 '='을 사용하자. 



◆ JOIN문만 사용 VS 서브쿼리만 사용 VS JOIN문 서브쿼리 사용

HR계정에서 "Seattle"에서 근무하는 모든 사원들을 조회하라" 라는 문제를 풀어보자

1. JOIN문만 사용해서 풀어보기

1
2
3
4
5
6
7
8
9
SELECT  *
FROM    EMPLOYEES EM
        , DEPARTMENTS DE
        , LOCATIONS LO
WHERE   EM.DEPARTMENT_ID = DE.DEPARTMENT_ID
AND     DE.LOCATION_ID = LO.LOCATION_ID
AND     LO.CITY = 'Seattle'
;
 
cs

2. 서브쿼리만 사용해서 풀어보기

1
2
3
4
5
6
7
8
9
10
11
12
SELECT  *
FROM    EMPLOYEES EM
WHERE   EM.DEPARTMENT_ID IN (
                                SELECT  DE.DEPARTMENT_ID
                                FROM    DEPARTMENTS DE
                                WHERE   DE.LOCATION_ID = (
                                                            SELECT  LO.LOCATION_ID
                                                            FROM    LOCATIONS LO
                                                            WHERE   LO.CITY = 'Seattle'
                                                         )
                           );
 
cs


3. JOIN문과 서브쿼리를 사용해서 풀어보기

SELECT  *
FROM    EMPLOYEES EM
        , DEPARTMENTS DE
WHERE   EM.DEPARTMENT_ID = DE.DEPARTMENT_ID
AND     DE.LOCATION_ID = (
                            SELECT  LOCATION_ID
                            FROM    LOCATIONS
                            WHERE   CITY = 'Seattle'
                         );


'Database > SQL' 카테고리의 다른 글

HR 계정 SQL 50문제  (0) 2018.08.17
SQL 50문제 실습하기  (0) 2018.08.17
데이터베이스 설계  (0) 2018.08.07

+ Recent posts