5. HAVING절의 서브 쿼리
HAVING절은 그룹 함수로 검색된 데이터 간 비교할 때 사용한다.
EX ) 직업과 직업별 토탈 월급을 출력하는데, 직업이 SALESMAN인 사원들의 토탈 월급보다 더 큰 값들만 출력하시오
직업이 SALESMAN인 사원이라는 조건이 있기 때문에 WHERE절을 사용해 작성할 수도 있다.
SELECT JOB, SUM(SAL)
FROM EMP
WHERE SUM(SAL) > (SELECT SUM(SAL)
FROM EMP
WHERE JOB = 'SALESMAN')
GROUP BY JOB;
하지만 그룹 함수로 검색조건을 작성했기 때문에 에러가 발생한다. 이 처럼 그룹 함수로 검색조건을 작성할 때는 HAVING절을 사용해야한다.
SELECT JOB SUM(SAL)
FROM EMP
GROUP BY JOB
HAVING SUM(SAL) > (SELECT SUM(SAL)
FROM EMP
WHERE JOB = 'SALESMAN');
SELECT 문에서 사용할 수 있는 서브 쿼리 문
SELECT문의 6가지 절 | 서브 쿼리 사용 여부 | 서브 쿼리 이름 |
SELECT | 가능 | Scalar 서브 쿼리 |
FROM | 가능 | IN LINE VIEW |
WHERE | 가능 | 서브 쿼리 |
GROUP BY | 불가능 | |
HAVING | 가능 | 서브 쿼리 |
ORDER BY | 가능 | Scalar 서브 쿼리 |
6. FROM절의 서브 쿼리
쿼리의 결과로 새로운 결과 집합을 만들 때 FROM절에 서브쿼리를 사용한다.
EX ) 이름과 월급의 순위를 출력하는데 월급의 순위가 1위인 사원만 출력하시오
만약 서브쿼리를 사용하지 않고 WHERE절을 사용해 작성하면 아래와 같이 작성할 수도 있다.
SELECT ENAME, SAL, RANK () OVER(ORDER BY SAL DESC) 순위
FROM EMP
WHERE RANK () OVER(ORDER BY SAL DESC) = 1;
하지만 위와 같이 작성하면 윈도우 함소를 여기에 사용할 수 없다는 에러가 발생한다. 이는 WHERE절에서 분석 함수를 사용할 수 없음을 의미한다.
따라서 FROM절에 서브 쿼리문을 사용하여 서브 쿼리문이 먼저 실행되게 하고 출력된 결과 데이터를 하나의 집합으로 만든다.
SELECT V.ENAME, V.SAL V.순위
FROM (SELECT ENAME, SAL, RANK () OVER(ORDER BY SAL DESC) 순위
FROM EMP) V
WHERE V.순위 = 1;
FROM절에서 만든 결과 집합은 사원 테이블의 모든 이름과 월급, 월급에 대한 순위이다. 이중에서 월급의 순위가 1위인 사원의 데이터만을 출력한다.
7. SELECT절의 서브 쿼리
서브 쿼리로 단일 값을 조회할 때 SELECT절의 서브 쿼리를 사용한다.
EX ) 직업이 SALESMAN인 사원들의 이름과 월급을 출력하는데, 직업이 SALESMAN인 사원들의 최대 월급과 최소 월급도 같이 출력하시오
만약 SELECT절의 서브 쿼리를 사용하지 않고 나타낸다면 아래와 같이 작성할 수도 있다.
SELECT ENAME, SAL, MAX(SAL), MIN(SAL)
FROM EMP
WHERE JOB = 'SALESMAN';
하지만 위와 같이 작성하면 단일 그룹의 그룹 함수가 아니라는 에러가 발생한다. SELECT 절에서 MAX(SAL)과 MIN(SAL)같은 경우 단일 값을 조회하지만 ENAME과 SAL의 경우 다중 행을 출력하기 때문에 에러가 발생한다.
이와 같은 문제를 해결하기 위해 SELECT절의 서브 쿼리를 사용한다.
SELECT ENAME, SAL, (SELECT MAX(SAL) FROM EMP WHERE JOB = 'SALESMAN') 최대_월급,
(SELECT MIN(SAL) FROM EMP WHERE JOB = 'SALESMAN') 최소_월급
FROM EMP
WHERE JOB = 'SALESMAN';
이 처럼 SELECT절의 서브 쿼리는 서브 쿼리가 SELECT절로 확장되었다고 해서 스칼라(Scalar) 서브 쿼리로 불린다. 스칼라 서브 쿼리는 출력되는 행 수만큼 반복되어 실행된다.
서브 쿼리 캐싱(CACHING)
위의 예제에서 같은 SQL이 반복되어 4번이나 실행되면서(SELECT MAX(SAL) FROM EMP WHERE JOB = 'SALESMAN'과 SELECT MIN(SAL) FROM EMP WHERE JOB = 'SALESMAN')같은 데이터를 반복해서 출력하므로 성능을 위해 첫 번째 행을 출력할 때 직업이 SALESMAN인 사원의 최대 월급과 최소 월급을 메모리에 올려 놓고 두 번째 행부터는 메모리에 올려놓은 데이터를 출력한다. 이를 서브 쿼리 캐싱이라 한다.
'Study > SQL' 카테고리의 다른 글
[SQL] 서브쿼리를 사용해 데이터 입력, 수정, 삭제하기 (0) | 2023.01.13 |
---|---|
[SQL]데이터 입력, 수정, 삭제 - INSERT, UPDATE, DELETE, TRUNCATE, DROP (0) | 2023.01.11 |
[SQL] 서브 쿼리 사용하기 2 - NOT IN, EXISTS/NOT EXISTS (0) | 2023.01.09 |
[SQL] 서브 쿼리 사용하기 1 - 단일 행, 다중 행 (0) | 2022.01.10 |
[SQL]여러 테이블의 데이터를 조인해서 출력하기(ON절, USING절, NATURAL JOIN, LEFFT/RIGHT OUTER JOIN) (0) | 2021.11.08 |