취업준비/코딩테스트 문제 풀이

[프로그래머스 SQL 코딩테스트 연습] Lv3. 즐겨찾기가 가장 많은 식당 정보 출력 (MySQL)

상급닌자연습생 2024. 7. 17. 15:16

🤔 문제

다음은 식당의 정보를 담은 `REST_INFO` 테이블입니다. `REST_INFO` 테이블은 다음과 같으며 `REST_ID`, `REST_NAME`, `FOOD_TYPE`, `VIEWS`, `FAVORITES`, `PARKING_LOT`, `ADDRESS`, `TEL`은 식당 ID, 식당 이름, 음식 종류, 조회수, 즐겨찾기수, 주차장 유무, 주소, 전화번호를 의미합니다.

`REST_INFO` 테이블에서 음식종류별로 즐겨찾기수가 가장 많은 식당의 음식 종류, ID, 식당 이름, 즐겨찾기수를 조회하는 SQL문을 작성해주세요. 이때 결과는 음식 종류를 기준으로 내림차순 정렬해주세요.

 

 

예시

`REST_INFO` 테이블이 다음과 같을 때

 

SQL을 실행하면 다음과 같이 출력되어야 합니다.

 

 

 

 

 


💻 나의 풀이

WITH MOSTFAV AS(
    SELECT FOOD_TYPE, REST_ID, REST_NAME, FAVORITES
    FROM REST_INFO
    GROUP BY FOOD_TYPE
    ORDER BY FAVORITES DESC
)
SELECT *
FROM MOSTFAV
ORDER BY FOOD_TYPE DESC;

 

 

 

 

결과

 

 

 


🖍 오답노트

틀린 이유

`GROUP BY`는 그룹화된 각 그룹에서 하나의 행을 반환하는 데,

`FAVORITES`를 기준으로 정렬하여 가장 많은 즐겨찾기를 가진 식당을 얻으려면 서브쿼리와 윈도우 함수를 사용해야 한다.

 

 

 

 

정답 풀이

1. 서브쿼리 내에서 MAX()로 최댓값을 찾는 풀이

SELECT FOOD_TYPE, REST_ID, REST_NAME, FAVORITES
FROM REST_INFO
WHERE (FOOD_TYPE, FAVORITES) IN (SELECT FOOD_TYPE, MAX(FAVORITES)
                                FROM REST_INFO
                                GROUP BY FOOD_TYPE)
ORDER BY 1 DESC;
  1. `WHERE (FOOD_TYPE, FAVORITES) IN ()`
    괄호 안을 만족하는 테이블을 돌면서 음식 종류와 즐겨찾기수를 비교하여 최다 즐겨찾기수와 해당하는 식당의 음식 종류를 필터링한다. 이때, 음식 종류와 즐겨찾기수가 (가리키는 식당이)같아야 하기 때문에 `(FOOD_TYPE, FAVORITES)`로 묶어준다.
  2. 서브쿼리
    음식 종류별로 최다 즐겨찾기수를 구하기 위해 `GROUP BY FOOD_TYPE`로 그룹핑한 후, `MAX(FAVORITES)`로 최댓값을 따로 찾아준다.

 

 

 

 

 

 

2. 윈도우 함수를 사용해서 음식 종류별 순위를 매기는 풀이

-- 음식 종류별 즐겨찾기수 기준으로 내림차순 정렬하여 순위를 매긴 테이블 생성
WITH RANKED_RESTS AS (
    SELECT 
        REST_ID, 
        REST_NAME, 
        FOOD_TYPE, 
        FAVORITES,
        ROW_NUMBER() OVER (PARTITION BY FOOD_TYPE ORDER BY FAVORITES DESC) AS RNK
    FROM REST_INFO
)
SELECT FOOD_TYPE, REST_ID, REST_NAME, FAVORITES
FROM RANKED_RESTS
WHERE RNK = 1
ORDER BY 1 DESC;
  1. CTE `RANKED_RESTS`
    음식 종류별 즐겨찾기수 기준으로 내림차순 정렬하여 각 식당에 대한 순위를 매긴 테이블을 생성한다.
    1. 윈도우 함수`ROW_NUMBER()` : `FOOD_TYPE`별로 즐겨찾기 수가 많은 순서대로 각 행에 번호를 매기는데,
    2. `PARTITION BY FOOD_TYPE` : 음식 종류별로 파티션을 나누고,
    3. `ORDER BY FAVORITES DESC` : 각 파티션 내에서 즐겨찾기수가 많은 순서대로 내림차순 정렬한다.
  2. 메인쿼리
    1. `RNK = 1` : 각 음식 종류별로 즐겨찾기 수가 가장 많은 식당(순위가 1번째인)을 선택한다.

 

 

 

 

 

 


✅ 핵심 정리

1. GROUP BY

`GROUP BY`로 그룹핑하면, 그룹 내에서 가장 상단에 있는 데이터들을 임의로 가져온다.

그래서 위의 문제에서 `GROUP BY FOOD_TYPE`후 그냥 `MAX(FAVORITES)`를 하게 되면, 음식 종류별 즐겨찾기수 최댓값이 아니라, 음식 종류별로 묶은 그룹 테이블 내 임의의 최상단 값을 조회하기 때문에 오답처리된다.

► 따라서 서브 쿼리를 생성하여 그 안에서 그룹핑하고 즐겨찾기수에 대한 최댓값을 따로 찾아줘야한다.

 

 

 

2. IN

: 값 리스트에 포함된 값을 검사하기 때문에 여러 행과 컬럼을 동시에 비교할 수 있다.

 

서브 쿼리를 생성했을 때, 다중 조건을 동시에 만족하기 위해서는 아래와 같이 쿼리를 작성해야 한다.

SELECT 컬럼명
FROM 테이블명
WHERE (컬럼명1, 컬럼명2, ..) IN (SELECT 서브쿼리_컬럼명1, 서브쿼리_컬럼명2, .. 
							FROM 서브쿼리_테이블명);

 

※ `=` 연산자

단일 값과의 비교에 사용되기 때문에 위와 같은 여러 컬럼을 동시에 비교하고자 할 때에는 `IN`을 사용해야 한다.

 

 

 

 

 

 

 

 


🔗 References

[풀이1 참고]

https://school.programmers.co.kr/questions/38854

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

 

[IN 개념 참고]

https://jaehwaseo.tistory.com/24

 

프로그래머스 즐겨찾기가 가장 많은 식당 정보 출력하기 SQL(MySQL)

문제 다음은 식당의 정보를 담은 REST_INFO 테이블입니다. REST_INFO 테이블은 다음과 같으며 REST_ID, REST_NAME, FOOD_TYPE, VIEWS, FAVORITES, PARKING_LOT, ADDRESS, TEL은 식당 ID, 식당 이름, 음식 종류, 조회수, 즐겨찾

jaehwaseo.tistory.com