■ 서브쿼리란?
서브쿼리는 쿼리 안에 있는 쿼리문이다. 쿼리란 SELECT문을 참조할 때 사용한다. SELECT문이란 테이블에서 정보를 가져오기 위해 사용한다.
요약을 하자면, 테이블에서 정보를 가져오기 위해 SELCT문을 사용해서 또 다른 SELECT문을 참조한다고 풀이할 수 있다.
-- ALLEN의 직무와 같은 사람의 이름, 부서명, 급여, 직무를 출력하라.
-- JONES 가 속해있는 부서의 모든 사람의 사원번호, 이름, 입사일, 급여를 출력하라.
-- 전체 사원의 평균 임금보다 많은 사원의 사원번호, 이름, 부서명, 입사일, 지역, 급여를 출력하라.
공통점은 어떤 결과와 컬럼을 비교하기 위해 사용한다. 이러한 문제들은 서브쿼리문을 사용하지 않으면 문제를 해결 할 수 없다.
■ 서브쿼리 프로세스
-- FIRST_NAME이 STEVEN인 사원과 같은 부서에서 일을 하는 모든 사원들의 정보
이러한 문제가 있다고 가정을 해보자. 그럼 우선 아래와 같은 과정을 통해 문제를 해결하면 도움이 될 것이다.
1. 어떤 정보를 보고싶은가?
2. 정보가 어디 테이블에 있는가?
3. 조건은 무엇인가?
우리는 모든 사원들의 정보를 보고싶다. 그 다음 이러한 정보가 어디 테이블에 있는지 알아보니 EMPLOYEES라는 테이블에 있다. 마지막으로 이름이 Steven이라는 사원과 같은 부서에 근무해야 하는 조건에 만족해야 한다.
<Steven이라는 사원과 같은 부서를 조회할 때 문제직면>
| SELECT * FROM EMPLOYEES WHERE DEPARTMENT_ID = ????? ; | cs |
Steven과 같은 사람의 부서를 비교를 해야하는데 서브쿼리를 모른다면 문제를 해결 할 수 없다. 그렇다면 Steven의 부서를 출력하는 문을 적어보자
<Steven이라는 사람의 부서번호 출력하는 SELECT문>
| SELECT DEPARTMENT_ID FROM EMPLOYEES WHERE FIRST_NAME = 'Steven' ; | cs |
<출력결과>
출력결과 보니깐 두개가 나왔다. 그렇다면 동명인이 존재하는 것이다. 이런 상황에서 서브쿼리를 사용해보자. ???? 된 곳에 괄호를 쳐서 Steven의 부서를 출력하는 SELECT문을 넣으면 서브쿼리가 완성된다.
<서브 쿼리문>
| SELECT * FROM EMPLOYEES WHERE DEPARTMENT_ID = ( SELECT DEPARTMENT_ID FROM EMPLOYEES WHERE FIRST_NAME = 'Steven' ) ; | cs |
<출력문>
에러문이 나왔다. 그 이유는 동명인이 존재하기 때문이다. 서브쿼리문 안에는 출력결과는 2개가 나오는데 어떤 Steven을 말하는지 모르겠다. 라고 말하는 것이다.
<FIRST_NAME이 STEVEN인 사원과 같은 부서에서 일을 하는 모든 사원들의 정보 서브쿼리>
| SELECT * FROM EMPLOYEES WHERE DEPARTMENT_ID IN ( SELECT DEPARTMENT_ID FROM EMPLOYEES WHERE FIRST_NAME = 'Steven' ) ; | cs |
'='은 한 개의 데이터와 비교 할 때 쓰이기 때문에 'IN'을 사용하면 여러 개의 데이터와 비교할 수 있어서 문제를 해결 할 수 있다.
추가적으로 서브쿼리문에서는 공백을 사용하면 안된다. 주의하자.
그렇다면 위에 문제를 응용해서 Steven은 제외한다 라는 조건이 더 붙으면 어떻게 작성해야 할까?
<Steven은 제외한다 라는 조건이 추가>
| SELECT * FROM EMPLOYEES WHERE DEPARTMENT_ID IN ( SELECT DEPARTMENT_ID FROM EMPLOYEES WHERE FIRST_NAME = 'Steven' ) AND FIRST_NAME !='Steven' ; | cs |
◆ IN vs '='
<IN 사용>
| SELECT * FROM EMPLOYEES WHERE DEPARTMENT_ID IN (10, 20) ; | cs |
<'=' 사용>
| 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문만 사용해서 풀어보기
| 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. 서브쿼리만 사용해서 풀어보기
| 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'
);