SQL 기본문법 > 서브쿼리(SubQuery) - 사용 위치에 따른 서브쿼리

|

개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.


서브쿼리(SubQuery)

SQL문 내부에서 사용하는 SELECT문

서브쿼리는 WHERE, SELECT, FROM, HAVING절 안에 넣어 사용할 수 있고, 이러한 서브쿼리는 괄호안에 적어주어야 한다. 일반적으로 서브쿼리가 먼저 실행된 후 메인쿼리가 실행되는 순서로 작업이 이루어진다.

조건절에서 사용하는 서브쿼리

-- 문제: 고객 전체의 평균 마일리지보다 평균마일리지가 큰 도시에 대해
-- 도시명과 도시의 평균 마일리지를 보이시오
SELECT 도시, AVG(마일리지) 평균마일리지 FROM 고객 GROUP BY 1
HAVING AVG(마일리지) > (SELECT AVG(마일리지) FROM 고객);

INLINE VIEW

FROM 절에서 사용하는 서브쿼리

이때 뷰에는 별명을 지정해줘야하며, 인라인뷰의 별명은 테이블명처럼 사용가능하다.

-- 문제: 담당자명, 고객회사명, 마일리지, 도시, 해당도시의 평균 마일리지를 보이시오
-- 그리고 고객이 위치하는 도시의 평균 마일리지와 각 고객의 마일리지 간 차이도 함께 보이시오
SELECT 담당자명, 고객회사명, 마일리지, 고객.도시, 도시_평균마일리지, (도시_평균마일리지-마일리지) 차이 FROM 고객,
(SELECT 도시, AVG(마일리지)  as '도시_평균마일리지' FROM 고객 GROUP BY 1) as 도시별요약 
WHERE 고객.도시 = 도시별요약.도시;

Scalar SubQuery(스칼라서브쿼리)

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

서브쿼리의 값이 딱 1개의 값으로 도출되어야 하는 서브쿼리로 이 쿼리를 통해 반환되는 값을 메인쿼리에서 사용한다. 이때 서브쿼리의 결과로 행을 0개 반환한다면 메인쿼리의 결과는 null이고 2개 이상의 행이 반환된다면 오류가 발생한다.

-- 문제1: 고객번호, 담당자명과 고객의 최종 주문일을 보이시오
SELECT 고객번호, 담당자명, 
(SELECT MAX(주문일) 최종주문일 FROM 주문 WHERE 고객.고객번호 = 주문.고객번호) AS 최종주문일
FROM 고객;

CTE(Common Table Expression)

쿼리로 만든 임시데이터셋으로 WITH에서 정의

쿼리 내에서 여러번 참조가 가능하기때문에 재사용성이 좋으며, 하나의 쿼리를 논리적 블록으로 나눌 수 있어 가독성이 좋다.

-- 문제: 담당자명, 고객회사명, 마일리지, 도시, 해당도시의 평균 마일리지를 보이시오
-- 그리고 고객이 위치하는 도시의 평균 마일리지와 각 고객의 마일리지 간 차이도 함께 보이시오
-- 이를 CTE로 풀이하시오 
SELECT 담당자명, 고객회사명, 마일리지, 고객.도시, 도시_평균마일리지, (도시_평균마일리지-마일리지) 차이 FROM 고객,
(SELECT 도시, AVG(마일리지) as '도시_평균마일리지' FROM 고객 GROUP BY 1) as 도시별요약 
WHERE 고객.도시 = 도시별요약.도시;

-- CTE
WITH 도시별요약 AS (
    SELECT 도시, AVG(마일리지) AS 도시_평균마일리지
    FROM 고객
    GROUP BY 1
)

SELECT 담당자명, 고객회사명, 도시_평균마일리지, (도시_평균마일리지-마일리지) 차이 
FROM 고객, 도시별요약
WHERE 고객.도시 = 도시별요약.도시;