[Programmers] 식품분류별 가장 비싼 식품의 정보 조회하기
🚀 오답 풀이
-- FOOD_PRODUCT: PRODUCT_ID, PRODUCT_NAME, PRODUCT_CD, CATEGORY, PRICE
SELECT CATEGORY,
MAX(PRICE) AS MAX_PRICE,
PRODUCT_NAME
FROM FOOD_PRODUCT
WHERE CATEGORY IN ('과자', '국', '김치', '식용유')
GROUP BY CATEGORY
ORDER BY PRICE DESC
;
오답 풀이 결과
CATEGORY MAX_PRICE PRODUCT_NAME
김치 19000 맛있는배추김치
식용유 8950 맛있는콩기름
국 2900 맛있는미역국
과자 1950 맛있는포카칩
오답 풀이의 문제점
- GROUP BY와 SELECT의 관계를 명확히 이해하지 못함!
- GROUP BY CATEGORY를 사용했기 때문에, 각 CATEGORY별 MAX(PRICE)를 구하는 것까지는 올바름.
- 하지만 PRODUCT_NAME을 SELECT할 때, 어떤 기준으로 선택할지 명확히 지정하지 않았음.
- 즉, PRODUCT_NAME이 MAX(PRICE)와 정확히 매칭된 값인지 보장되지 않음.
- 🚨 그룹 내에서 임의의 PRODUCT_NAME이 선택될 가능성이 있음.
개선 방법
- PRODUCT_NAME도 GROUP BY 규칙을 만족하도록 처리
- 기존 쿼리에서는 PRODUCT_NAME이 GROUP BY 없이 사용되어 예측할 수 없는 값이 선택될 가능성이 있음.
- JOIN 활용 => MAX(PRICE)를 가진 제품과 정확히 매칭되는 PRODUCT_NAME select
- 데이터가 많을수록 IN보다 JOIN이 더 효율적
- JOIN을 사용하면 필요한 데이터만 매칭하여 불필요한 검색을 줄일 수 있음
- 특히, 대량 데이터를 처리할 때 JOIN이 IN보다 훨씬 빠르게 동작할 가능성이 높음
- 최적화된 방법
- CTE (WITH)를 사용하여 각 카테고리별 최대 가격을 만족하는 제품을 선언
- 해당 테이블을 JOIN하여 필요한 값(PRODUCT_NAME, CATEGORY, PRICE)을 가져옴
정답
-- FOOD_PRODUCT: PRODUCT_ID, PRODUCT_NAME, PRODUCT_CD, CATEGORY, PRICE
WITH MAX_PRICE_BY_CATEGORY AS (
SELECT CATEGORY, MAX(PRICE) AS MAX_PRICE
FROM FOOD_PRODUCT
GROUP BY CATEGORY
)
SELECT T1.CATEGORY AS CATEGORY, T1.PRICE AS MAX_PRICE, T1.PRODUCT_NAME AS PRODUCT_NAME
FROM MAX_PRICE_BY_CATEGORY AS T2
JOIN FOOD_PRODUCT AS T1
ON T1.CATEGORY = T2.CATEGORY
AND T1.PRICE = T2.MAX_PRICE
WHERE T2.CATEGORY IN ('과자', '국', '김치', '식용유')
ORDER BY MAX_PRICE DESC;
✅ Point
- JOIN에서 필터링 조건을 활용하여 불필요한 데이터 제거
- 작은 테이블을 기준으로 JOIN 수행