[프로그래머스 SQL/131116] 식품분류별 가장 비싼 식품의 정보 조회하기
in Study / Coding Test
☑️ 문제
- 카테고리 별 가장 비싼 상품을 가져오기
☑️ 풀이
첫 번째 풀이 (실패)
SELECT CATEGORY, PRICE AS 'MAX_PRICE', PRODUCT_NAME
FROM FOOD_PRODUCT
GROUP BY CATEGORY
HAVING CATEGORY IN ('과자', '국', '김치', '식용유')
ORDER BY PRICE DESC
- GROUP BY 사용 시 집계 함수 없이 SELECT 절에 PRICE, PRODUCT_NAME이 쓰였기 때문에, GROUP BY 된 각 그룹에서 임의의 하나의 레코드를 가져오는 에러가 발생한다.
CATEGORY IN ('과자', '국', '김치', '식용유')
도 HAVING 절이 아닌 WHERE 절에 쓰는 게 더 명확하다.- WHERE : 그룹화 전에 행 필터링
- HAVING : GROUP BY 이후 그룹 필터링
두 번째 풀이 (성공)
SELECT CATEGORY, PRICE AS 'MAX_PRICE', PRODUCT_NAME
FROM FOOD_PRODUCT
WHERE (CATEGORY, PRICE) IN (
SELECT CATEGORY, MAX(PRICE)
FROM FOOD_PRODUCT
WHERE CATEGORY IN ('과자', '국', '김치', '식용유')
GROUP BY CATEGORY
)
ORDER BY PRICE DESC
- 서브쿼리를 이용하여 카테고리별 최고 가격을 구한다.
- 메인쿼리에서는 서브 쿼리에서 구한
(CATEGORY, MAX_PRICE)
쌍을 기준으로, 원래 테이블에서 해당 상품을 찾는다.
세 번째 풀이 (성공)
SELECT CATEGORY, PRICE AS 'MAX_PRICE', PRODUCT_NAME
FROM (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY CATEGORY ORDER BY PRICE DESC) AS RN
FROM FOOD_PRODUCT
WHERE CATEGORY IN ('과자', '국', '김치', '식용유')
) T
WHERE RN = 1
ORDER BY PRICE DESC
PARTITION BY CATEGORY
: 카테고리별로 데이터를 묶는다.ORDER BY PRICE DESC
: 각 카테고리 안에서 가격 기준으로 내림차순 정렬을 한다.ROW_NUMBER()
: 정렬된 각 그룹 내에서 순번을 매긴다. (가장 비싼 상품은 rn = 1)- 외부 SELECT에서
WHERE RN = 1
: 각 카테고리에서 가장 비싼 상품 하나만 뽑는다.
☑️ 문법 정리
윈도우 함수
형식
<윈도우 함수> OVER ( [PARTITION BY ...] [ORDER BY ...] [ROWS BETWEEN ...] )
- 그룹 집계 없이도 행마다 통계 정보를 계산할 수 있는 함수
- OVER() 절과 함께 사용하며, GROUP BY와 달리 모든 행에 결과가 유지된다.
윈도우 함수 종류
함수 이름 설명 ROW_NUMBER()
정렬 기준에 따라 순번을 매김 (무조건 1,2,3…) RANK()
동순위 허용, 다음 순위 건너뜀 (예: 1,1,3) DENSE_RANK()
동순위 허용, 다음 순위 안 건너뜀 (예: 1,1,2) NTILE(N)
N개의 그룹으로 나눔 (백분위 등 만들 때 사용) SUM()
누적 합 계산 가능 AVG()
누적 평균 MAX()
,MIN()
누적 최대/최소값 LAG()
,LEAD()
이전/다음 행 값 참조 - PARTITION BY
- 데이터를 그룹으로 나누는 기준이다.
- GROUP BY처럼 동작하지만 결과는 원래 행 개수만큼 유지된다.
예시
ROW_NUMBER() OVER (PARTITION BY CATEGORY ORDER BY PRICE DESC)
- ROWS BETWEEN …
- 누적 계산 시 사용하는 범위를 지정한다. (누적합 등에서 사용)
예시
SUM(SALES) OVER ( PARTITION BY YEAR ORDER BY MONTH ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW )
- 올해 1월부터 현재 월까지의 누적 매출을 계산한다.