[프로그래머스] (MySQL) 88. 그룹별 조건에 맞는 식당 목록 출력하기

최재원's avatar
Jan 07, 2026
[프로그래머스] (MySQL) 88. 그룹별 조건에 맞는 식당 목록 출력하기
💡

문제 설명

다음은 고객의 정보를 담은 MEMBER_PROFILE테이블과 식당의 리뷰 정보를 담은 REST_REVIEW 테이블입니다. MEMBER_PROFILE 테이블은 다음과 같으며 MEMBER_IDMEMBER_NAMETLNOGENDERDATE_OF_BIRTH는 회원 ID, 회원 이름, 회원 연락처, 성별, 생년월일을 의미합니다.
Column name
Type
Nullable
MEMBER_ID
VARCHAR(100)
FALSE
MEMBER_NAME
VARCHAR(50)
FALSE
TLNO
VARCHAR(50)
TRUE
GENDER
VARCHAR(1)
TRUE
DATE_OF_BIRTH
DATE
TRUE
REST_REVIEW 테이블은 다음과 같으며 REVIEW_IDREST_IDMEMBER_IDREVIEW_SCOREREVIEW_TEXTREVIEW_DATE는 각각 리뷰 ID, 식당 ID, 회원 ID, 점수, 리뷰 텍스트, 리뷰 작성일을 의미합니다.
Column name
Type
Nullable
REVIEW_ID
VARCHAR(10)
FALSE
REST_ID
VARCHAR(10)
TRUE
MEMBER_ID
VARCHAR(100)
TRUE
REVIEW_SCORE
NUMBER
TRUE
REVIEW_TEXT
VARCHAR(1000)
TRUE
REVIEW_DATE
DATE
TRUE
💡

문제

MEMBER_PROFILE와 REST_REVIEW 테이블에서 리뷰를 가장 많이 작성한 회원의 리뷰들을 조회하는 SQL문을 작성해주세요. 회원 이름, 리뷰 텍스트, 리뷰 작성일이 출력되도록 작성해주시고, 결과는 리뷰 작성일을 기준으로 오름차순, 리뷰 작성일이 같다면 리뷰 텍스트를 기준으로 오름차순 정렬해주세요.

예시

MEMBER_PROFILE 테이블이 다음과 같고
MEMBER_ID
MEMBER_NAME
TLNO
GENDER
DATE_OF_BIRTH
jiho92@naver.com
이지호
01076432111
W
1992-02-12
jiyoon22@hotmail.com
김지윤
01032324117
W
1992-02-22
jihoon93@hanmail.net
김지훈
01023258688
M
1993-02-23
seoyeons@naver.com
박서연
01076482209
W
1993-03-16
yelin1130@gmail.com
조예린
01017626711
W
1990-11-30
REST_REVIEW 테이블이 다음과 같을 때
REVIEW_ID
REST_ID
MEMBER_ID
REVIEW_SCORE
REVIEW_TEXT
REVIEW_DATE
R000000065
00028
soobin97@naver.com
5
부찌 국물에서 샤브샤브 맛이나고 깔끔
2022-04-12
R000000066
00039
yelin1130@gmail.com
5
김치찌개 최곱니다.
2022-02-12
R000000067
00028
yelin1130@gmail.com
5
햄이 많아서 좋아요
2022-02-22
R000000068
00035
ksyi0316@gmail.com
5
숙성회가 끝내줍니다.
2022-02-15
R000000069
00035
yoonsy95@naver.com
4
비린내가 전혀없어요.
2022-04-16
SQL을 실행하면 다음과 같이 출력되어야 합니다.
MEMBER_NAME
REVIEW_TEXT
REVIEW_DATE
조예린
김치찌개 최곱니다.
2022-02-12
조예린
햄이 많아서 좋아요
2022-02-22

주의사항

REVIEW_DATE의 데이트 포맷이 예시와 동일해야 정답처리 됩니다.
 

코드 - in 을 사용한 방법

SELECT MP.MEMBER_NAME, RR.REVIEW_TEXT, DATE_FORMAT(RR.REVIEW_DATE, '%Y-%m-%d') AS REVIEW_DATE FROM REST_REVIEW RR INNER JOIN MEMBER_PROFILE MP ON RR.MEMBER_ID = MP.MEMBER_ID WHERE RR.MEMBER_ID IN ( SELECT MEMBER_ID FROM ( SELECT MEMBER_ID, RANK() OVER (ORDER BY COUNT(*) DESC) AS RANK_NUM FROM REST_REVIEW GROUP BY MEMBER_ID ) REVIEW WHERE RANK_NUM = 1 ) ORDER BY RR.REVIEW_DATE ASC, RR.REVIEW_TEXT ASC;
notion image

코드 - 서브쿼리 & join 을 사법

SELECT MP.MEMBER_NAME, RR.REVIEW_TEXT, DATE_FORMAT(RR.REVIEW_DATE, '%Y-%m-%d') AS REVIEW_DATE FROM REST_REVIEW RR JOIN MEMBER_PROFILE MP ON MP.MEMBER_ID = RR.MEMBER_ID JOIN ( SELECT MEMBER_ID FROM REST_REVIEW GROUP BY MEMBER_ID HAVING COUNT(*) = ( SELECT MAX(cnt) FROM ( SELECT COUNT(*) AS cnt FROM REST_REVIEW GROUP BY MEMBER_ID ) t ) ) TOPPER ON TOPPER.MEMBER_ID = RR.MEMBER_ID ORDER BY RR.REVIEW_DATE ASC, RR.REVIEW_TEXT ASC;
 

두 방식의 차이점

구분
첫 번째 쿼리 (RANK)
두 번째 쿼리 (HAVING = MAX)
핵심 방식
RANK() OVER (ORDER BY COUNT(*) DESC) 사용
HAVING COUNT(*) = (SELECT MAX(cnt) …) 사용
의존 기능
윈도 함수 필요 (MySQL 8.0 이상)
집계와 서브쿼리만 사용 (MySQL 5.7도 가능)
계산 구조
한 번의 GROUP BY + 윈도 함수
GROUP BY 두 번 수행 (내부·외부)
성능
상대적으로 효율적 (집계 1회)
중첩 집계로 약간 비효율적
조인 형태
WHERE … IN (subquery) 세미조인
명시적 JOIN (파생 테이블 결합)
가독성
직관적, 짧음
더 길고 중첩 많음
이식성
낮음 (윈도 함수 미지원 DB 불가)
높음 (모든 주요 DB 지원)
결과
동점자 모두 반환
동일
추천 상황
MySQL 8.0 이상 환경
MySQL 5.7 이하, 호환성 중시
요약:
  • 최신 MySQL이면 RANK() 쿼리가 빠르고 간결하다.
  • 구버전이나 타 DB 호환을 원하면 HAVING = MAX 쿼리가 안전하다.
 

힌트

WITH CustomerCounts AS ( -- 1. 고객별 주문 건수를 계산하고 순위를 매기는 CTE (Common Table Expression) SELECT customer_id, COUNT(*) AS order_count, -- 주문 건수에 따라 순위(rank_num)를 매김. 동률은 같은 순위 부여. RANK() OVER (ORDER BY COUNT(*) DESC) AS rank_num FROM Orders GROUP BY customer_id ) SELECT T1.* -- Orders 테이블의 모든 주문 정보 (T1) FROM Orders T1 INNER JOIN CustomerCounts T2 ON T1.customer_id = T2.customer_id -- 주문 정보와 순위 정보를 고객 ID로 연결 WHERE T2.rank_num = 1; -- 순위가 1인 (가장 많은 주문을 한) 고객의 주문만 선택
  • 주문테이블에서 가장많은 주문을 한 고객의 모든 주문정보
  • 동률도 찾아줌
 
Share article

jjack1