프로그래머스에서 제공하는 SQL문제 매일 풀기 챌린지
문제 설명
다음은 식품의 정보를 담은 FOOD_PRODUCT 테이블입니다. FOOD_PRODUCT 테이블은 다음과 같으며 PRODUCT_ID, PRODUCT_NAME, PRODUCT_CD, CATEGORY, PRICE는 식품 ID, 식품 이름, 식품코드, 식품분류, 식품 가격을 의미합니다
Column name | Type | Nullable |
PRODUCT_ID | VARCHAR(10) | FALSE |
PRODUCT_NAME | VARCHAR(50) | FALSE |
PRODUCT_CD | VARCHAR(10) | TRUE |
CATEGORY | VARCHAR(10) | TRUE |
PRICE | NUMBER | TRUE |
문제
FOOD_PRODUCT 테이블에서 식품분류별로 가격이 제일 비싼 식품의 분류, 가격, 이름을 조회하는 SQL문을 작성해주세요. 이때 식품분류가 '과자', '국', '김치', '식용유'인 경우만 출력시켜 주시고 결과는 식품 가격을 기준으로 내림차순 정렬해주세요.
예시
FOOD_PRODUCT 테이블이 다음과 같을 때
PRODUCT_ID | PRODUCT_NAME | PRODUCT_CD | CATEGORY | PRICE |
P0018 | 맛있는고추기름 | CD_OL00008 | 식용유 | 6100 |
P0019 | 맛있는카놀라유 | CD_OL00009 | 식용유 | 5100 |
P0020 | 맛있는산초유 | CD_OL00010 | 식용유 | 6500 |
P0021 | 맛있는케첩 | CD_SC00001 | 소스 | 4500 |
P0022 | 맛있는마요네즈 | CD_SC00002 | 소스 | 4700 |
P0039 | 맛있는황도 | CD_CN00008 | 캔 | 4100 |
P0040 | 맛있는명이나물 | CD_CN00009 | 캔 | 3500 |
P0041 | 맛있는보리차 | CD_TE00010 | 차 | 3400 |
P0042 | 맛있는메밀차 | CD_TE00001 | 차 | 3500 |
P0099 | 맛있는맛동산 | CD_CK00002 | 과자 | 1800 |
SQL을 실행하면 다음과 같이 출력되어야 합니다.
CATEGORY | MAX_PRICE | PRODUCT_NAME |
식용유 | 6500 | 맛있는산초유 |
과자 | 1800 | 맛있는맛동산 |
♥ 정답
select category, price as max_price, product_name
from (select category, product_name, price,
rank() over (partition by category order by price desc ) as rnk
from food_product) d
where category in ('과자', '국', '김치', '식용유')
and rnk = 1
order by max_price desc;
이 문제는
in line view (FROM절의 서브쿼리)와 RANK 윈도우함수
위 2가지를 사용하여 해결하였다.
■ EQUI JOIN
조인은 여러 개의 테이블의 컬럼들을 활용하여 한 번에 원하는 것을 출력하고자 할 때 사용하는 문법이다.
그 중 EQUI JOIN 이란,
조인하려는 테이블 사이에 공통된 컬럼이 있을 경우 (컬럼명은 달라도 되고, 데이터가 공통될 때)
EQUAL(=) 조인하는 조인 문법이다.
ORACLE과 MySQL의 차이점은
MySQL에서는 IN LINE VIEW에 별칭을 지정해줘야 오류가 발생하지 않는 것이다.
ORACLE은 별칭이 없어도 에러가 발생하지 않았다.
■ 윈도우 함수(Window function)
윈도우 함수는 특정 창(Window) 또는 그룹 내에서 데이터를 처리하고 계산하는 데 사용된다.
일반적으로 집계 함수와는 달리 개별 행에 대한 계산을 수행하며
데이터 집합을 여러 그룹으로 나눌 필요 없이 전체 데이터 집합에 대해 작동한다.
윈도우 함수는 OVER절을 사용하여 정의하고, 윈도우의 파티션(분할 기준), 정렬 순서(ORDER BY), 윈도우 프레임(계산 대상 행의 범위) 등을 지정할 수 있다.
주로 아래와 같은 상황에서 사용한다.
- 순위를 계산하는 함수 : RANK(), DENSE_RANK(), ROW_NUMBER() 등
- 누적 합, 평균, 최소값, 최대값 계산: `SUM()`, `AVG()`, `MIN()`, `MAX()` 등
♥ 해설해보기
#IN LINE VIEW
메인쿼리에서 출력되어야할 컬럼명들을 나열해주고,
마지막에 순위를 구하기 위해서 RANK() 윈도우함수를 사용해준다.
CATEGORY 별 순위를 구해야하기 때문에 PARTITION 을 CATEGORY 별로 나누어주고,
가장 비싼 식품의 가격을 조회해야 하기 때문에 PRICE컬럼을 기준으로 DESC하게 정렬해준다.
마지막으로 메인쿼리에서 사용하기 위해서 별칭을 지정해준다.
rank() over (partition by category order by price desc) rnk
#MAIN QUERY
IN LINE VIEW 에서 출력된 결과는
FOOD_PRODUCT 테이블에서 식품분류별로 가격의 순위를 구한 RNK와
CATEGORY, PRODUCT_NAME, PRICE 이다.
위 결과를 가지고 문제의 요구를 충족하기 위해 분류, 가격, 이름을 조회하기 위해 아래와 같이 SELECT절을 작성한다.
SELECT category, price as max_price, product_name
max_price로 설정된 컬럼을 충족하기 위해서
in line view에서 생성했던 식품분류별 가격 순위 컬럼인 rnk를 활용하여 where절에서 rnk=1로 제한해준다.
이렇게 되면 식품분류별 가격이 제일 비싼 식품에 대해서만 조회할 수 있다.
추가적으로 식품분류는 '과자', '국', '김치', '식용유'인 경우만 출력되어야하기 때문에 in을 사용하여 제한해준다.
WHERE category in ('과자', '국', '김치', '식용유')
마지막으로 max_price를 기준으로 desc하게 정렬해준다.
결과 출력
출처 : 프로그래머스 코딩 테스트 연습, https://school.programmers.co.kr/learn/challenges
'SQL 문제 풀기 > 1. 프로그래머스 SQL : 2023.12.17~2024.2.29' 카테고리의 다른 글
<프로그래머스 65> 취소되지 않은 진료 예약 조회하기(Lv.4) (0) | 2024.02.19 |
---|---|
<프로그래머스 64> 5월의 식품들의 총매출 조회하기(Lv.4) (0) | 2024.02.18 |
<프로그래머스 62> 보호소에서 중성화한 동물(Lv.4) (0) | 2024.02.16 |
<프로그래머스 61> 대여 횟수가 많은 자동차들의 월별 대여 횟수 구하기(Lv.3) (0) | 2024.02.15 |
<프로그래머스 60> 조회수가 가장 많은 중고거래 게시판의 첨부파일 조회하기(Lv.3) (2) | 2024.02.14 |