Skip to main content

[SQL] 131123 즐겨찾기가 가장 많은 식당 정보 출력하기

https://school.programmers.co.kr/learn/courses/30/lessons/131123

image.png

image.png

📌문제

  • ​테이블 : REST_INFO
  • 조건
    • 음식 종류별로 즐겨찾기가 가장 많은 식당의
    • 음식 종류, ID, 식당이름, 즐겨찾기 수
  • 정렬
    • 음식 종류 기준 내림차순

💡 정답쿼리

CTE + ROW_NUMBER() + PARTITION BY

이건 윈도우 함수 써서 푼 방식이다. 전체 테이블 스캔 후에 FOOD_TYPE 별로 그룹을 나누고, 각 그룹 안에서 FAVORITES 내림차순 정렬한다. 순위 계산 후 rn = 1 필터링한다. 이렇게 하면 가독성이 좋다.

WITH ranked_rest AS (
    SELECT rest_id,
           rest_name,
           food_type,
           favorites,
           ROW_NUMBER() OVER (PARTITION BY food_type ORDER BY favorites DESC) AS rn
    FROM rest_info
)
SELECT FOOD_TYPE, REST_ID, REST_NAME, FAVORITES
FROM ranked_rest
WHERE rn = 1
ORDER BY food_type DESC;
  1. ROW_NUMBER() + PARTITION BY FOOD_TYPE
    → 음식 종류별로 순위 매기기
  2. ORDER BY FAVORITES DESC
    → 즐겨찾기 수가 높은 순으로 정렬해서 1위만 가져오기
  3. 마지막에 WHERE rn = 1로 각 음식 종류의 최상위 식당만 필터링,
  4. 결과는 ORDER BY FOOD_TYPE DESC 로 음식 종류 기준 내림차순

하지만 MySQL은 윈도 함수 계산시 내부적으로 정렬이 필요하므로 큰 데이터에서 메모리랑 정렬 비용이 크다.

GROUP BY + MAX()

SELECT r.FOOD_TYPE, r.REST_ID, r.REST_NAME, r.FAVORITES
FROM REST_INFO r
JOIN (
    SELECT FOOD_TYPE, MAX(FAVORITES) AS max_fav
    FROM REST_INFO
    GROUP BY FOOD_TYPE
) m ON r.FOOD_TYPE = m.FOOD_TYPE AND r.FAVORITES = m.max_fav
ORDER BY r.FOOD_TYPE DESC;
  1. GROUP BY로 각 음식 종류별 최대 즐겨찾기 수 계산하기
  2. 원본 테이블과 조인해서 해당 최대값을 가진 레코드 가져오기

이렇게 하면 보통 윈도우 함수보다 메모리 사용량이 적다.

결론

  • 데이터가 수십만 건 이상이고 단순히 "그룹별 최댓값"만 구한다면 GROUP BY + MAX() 방식이 더 빠르다.
  • 하지만 앞으로 "그룹별 상위 N개" 같은 요구가 생길 수 있다면 처음부터 ROW_NUMBER()을 쓰는게 유지보수에 좋다.