본문 바로가기
데이터베이스

11. SUB QUERY

by 김마리님 2020. 4. 2.

이전부터 많이 썼던 서브쿼리는, 하나 이상의 조건을 한 문단에 처리하기 위해 사용하는 기법이다.

쿼리 안에 다른 쿼리를 담는 형태를 의미한다.

바깥에 있는 쿼리를 메인 쿼리, 내부에 있는 쿼리를 서브 쿼리라고 한다.

 

서브쿼리의 간단한 예시는 다음과 같다.

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

매우 익숙한 모습이다.

 

서브쿼리는 주의할 점이 있다.

다음과 같은 쿼리를 보자.

SELECT *
FROM EMP
WHERE SAL= (SELECT SAL
FROM EMP
WHERE JOB = 'MANAGER');

이 쿼리를 실행시켜보면

다음과 같은 오류가 뜬다.

내부에 있는 쿼리만 실행시켜보면,

3개 행이 실행되어 있음을 볼 수 있다. 그렇기 때문에 서브쿼리에서 어떤 값을 써야할 지 알 수 없게 되어버린 것이다. 이렇게 행이 두개 이상 나오게 되는 것을 다중 행 서브쿼리라고 한다.

 

단일행 서브쿼리에 들어가는 연산자는 다음과 같다.

= 같다
<> 같지 않다
> 크다
>=  크거나 같다
< 작다
<= 작거나 같다.

다음과 같은 연산자는 아주 익숙하므로, 바로 다중 행 서브쿼리를 보자.

IN 서브쿼리 결과와 같은 값을 찾는다.
EXISTS 서브쿼리의 값이 있을 경우 메인쿼리를 수행한다
>ANY 서브쿼리 결과 중 최솟값 반환
<ANY 서브쿼리 결과 중 최대값 반환
>ALL 서브쿼리 결과 중 최대값 반환
<ANY 서브쿼리 결과 중 최솟값 반환

따라서, 위의 오류는 다음과 같이 해결할 수 있을 것이다.

SELECT *
FROM EMP
WHERE SAL IN (SELECT SAL
FROM EMP
WHERE JOB = 'MANAGER');

 

ANY를 쓰는 서브쿼리의 예시를 보자.

SELECT NAME,EMP_TYPE,TO_CHAR(PAY,'$999,999,999') SALARY
FROM EMP2
WHERE PAY>ANY(SELECT PAY FROM EMP2 WHERE EMP_TYPE='정규직');

>ANY는 최솟값을 찾는 다중 행 서브쿼리 연산자이다.

다음 쿼리는 정규직의 최솟값보다 높은 연봉을 받는 사람을 찾는 쿼리이다.

 

다중행 쿼리를 이용하지 않으려면 그룹함수를 이용하면 되기는 한다.

SELECT NAME,EMP_TYPE,PAY
FROM EMP2
WHERE PAY>(
SELECT MIN(PAY) 
FROM EMP2 
WHERE EMP_TYPE='정규직'
);

 

ALL을 이용한 예시도 보자.

SELECT NAME, GRADE, WEIGHT
FROM STUDENT
WHERE WEIGHT<ALL(SELECT WEIGHT FROM STUDENT WHERE GRADE=2);

<ALL이므로, 이 값도 최솟값을 찾는 다중행 서브쿼리이다.

즉, 2학년 학생 중 무게가 제일 적은 학생보다 작은 무게를 가지는 학생을 찾는 쿼리이다.

 

이것 역시 다중행 서브쿼리 연산자를 이용하지 않으려면 그룹함수를 이용하면 된다.

SELECT NAME, GRADE, WEIGHT
FROM STUDENT
WHERE WEIGHT<(SELECT MIN(WEIGHT) FROM STUDENT WHERE GRADE=2);

 

서브쿼리와 그룹함수가 함께 쓰인 예시도 보자.

SELECT D.DNAME,E.NAME,E.PAY 
FROM DEPT2 D, EMP2 E
WHERE E.DEPTNO=D.DCODE AND PAY<ALL(
SELECT AVG(PAY)
FROM EMP2
GROUP BY DEPTNO
);

이 함수는 부서의 평균연봉 중 제일 낮은 평균보다 낮은 연봉을 받는 사람을 찾는 쿼리이다.

 

이 쿼리도 마찬가지로 그룹함수화 할 수 있는데,

SELECT D.DNAME,E.NAME,E.PAY 
FROM DEPT2 D, EMP2 E
WHERE E.DEPTNO=D.DCODE AND PAY<(
SELECT MIN(APAY)
FROM
(SELECT AVG(PAY) "APAY"
FROM EMP2
GROUP BY DEPTNO));

앞서 말한 적 있는데, SELECT 가 많아질 수록 연산이 느려진다. 따라서, 그룹함수보다 연산자등을 써서 SELECT를 줄이는 것도 한 방법이다.

반응형

'데이터베이스' 카테고리의 다른 글

12. 스칼라 서브쿼리  (0) 2020.04.08
데이터 검색 기법  (0) 2020.04.02
10. DML  (0) 2020.04.02
9. view  (0) 2020.04.02
DDL, DML과 시퀀스 체험하기  (0) 2020.04.01