처리해야 하는 연산의 수가 커질수록 쿼리문은 길어지게 된고 그러면 가독성이 줄어들고 한번에 여러 연산을 하여 효율적이지 않다. 이를 가독성을 높이고 효율을 높이기 위해 Subquery를 사용한다.
SELECT 컬럼
FROM
(
SELECT 컬럼
FROM 테이블
)
쿼리문 안에 쿼리문을 넣은 듯한 모양을 가진다.
2개 이상도 가능
필요한 데이터가 각각 다른 테이블에 있을 경우 하나의 테이블로 합쳐서 사용하게 해준다.
공통 컬럼을 기준으로 테이블을 합친다.
JOIN을 하면 SELECT 문에서 컬럼
이 아닌 테이블.컬럼
또는 AS를 사용한다면 A.컬럼
형식으로 사용해야 한다.
LEFT JOIN
SELECT
A.컬럼,
B.컬럼
FROM 테이블 A LEFT JOIN 테이블 B ON A.공통컬럼=B.공통컬럼
LEFT JOIN 은 테이블 A에 테이블 B의 데이터를 합치는 것으로 테이블 A에는 있지만 테이블 B에 없는 데이터는 NULL로 처리된다.
INNER JOIN
SELECT
A.컬럼,
B.컬럼
FROM 테이블 A INNER JOIN 테이블 B ON A.공통컬럼=B.공통컬럼
INNER JOIN 은 벤 다이어그램의 합집합으로 이해하면 쉽다.
테이블 A와 테이블 B에 둘 다 있는 데이터만 합친다.
RIGHT JOIN 도 있지만 LEFT JOIN과 합치는 방향만 다를 뿐 동일하다.
식당별 평균 음식 주문 금액과 주문자의 평균 연령을 기반으로 Segmentation하기
-평균 음식 주문 금액 기준: 5000/10000/30000/30000 초과
-평균 연령: ~20대/30대/40대/50대 이상
JOIN
식당, 음식 주문 금액: food_orders 테이블
주문자의 연령: customers 테이블
공통 컬럼: customer_id
GROUP BY
식당별: restaurant_name
SELECT fo.restaurant_name,
AVG(fo.price) avg_price,
AVG(c.age) avg_age
FROM food_orders fo inner join customers c on fo.customer_id=c.customer_id
GROUP BY 1
평균 주문 음식 금액, 평균 연령 기준 분류: CASE
SELECT restaurant_name,
CASE
when avg_price>30000 then 'price_group4'
when avg_price>10000 then 'price_group3'
when avg_price>5000 then 'price_group2'
else 'price_group1'
END price_group,
CASE
when avg_age>=50 then 'age_group4'
when avg_age>=40 then 'age_group3'
when avg_age>=30 then 'age_group2'
else 'age_group1'
END age_group
FROM
(
SELECT fo.restaurant_name,
AVG(fo.price) avg_price,
AVG(c.age) avg_age
FROM food_orders fo inner join customers c on fo.customer_id=c.customer_id
GROUP BY 1
) a
ORDER BY 1
Subquery 의 SELECT 에서는 테이블.컬럼
형식을 사용하지만 1번 줄의 SELECT에서는 사용하지 않는 것은 Subquery 한 테이블을 아래와 같이 a라는 하나의 테이블로 처리하기 때문
SELECT restaurant_name,
CASE
when avg_price>30000 then 'price_group4'
when avg_price>10000 then 'price_group3'
when avg_price>5000 then 'price_group2'
else 'price_group1'
END price_group,
CASE
when avg_age>=50 then 'age_group4'
when avg_age>=40 then 'age_group3'
when avg_age>=30 then 'age_group2'
else 'age_group1'
END age_group
FROM a
ORDER BY 1