프로그래머스 SQL 고득점 Kit
https://school.programmers.co.kr/learn/challenges?tab=sql_practice_kit
MEMBER_PROFILE와 REST_REVIEW 테이블에서 리뷰를 가장 많이 작성한 회원의 리뷰들을 조회하는 SQL문을 작성해주세요.
회원 이름, 리뷰 텍스트, 리뷰 작성일이 출력되도록 작성해주시고, 결과는 리뷰 작성일을 기준으로 오름차순, 리뷰 작성일이 같다면 리뷰 텍스트를 기준으로 오름차순 정렬해주세요.
SELECT
P.MEMBER_NAME,
R.REVIEW_TEXT,
DATE_FORMAT(R.REVIEW_DATE, '%Y-%m-%d') AS REVIEW_DATE
FROM MEMBER_PROFILE AS P
JOIN REST_REVIEW AS R
ON R.MEMBER_ID = P.MEMBER_ID
JOIN (
-- 회원별 리뷰수 집계
SELECT MEMBER_ID, COUNT(*) AS REVIEW_COUNT
FROM REST_REVIEW
GROUP BY MEMBER_ID
) AS C
ON C.MEMBER_ID = P.MEMBER_ID
WHERE C.REVIEW_COUNT = (
-- 집계한 리뷰수들 중 최댓값과 비교
SELECT MAX(X.REVIEW_cOUNT)
FROM (
SELECT MEMBER_ID, COUNT(*) AS REVIEW_COUNT
FROM REST_REVIEW
GROUP BY MEMBER_ID
) AS X
)
ORDER BY R.REVIEW_DATE ASC, R.REVIEW_TEXT ASC;
슬슬 한 문제 풀때 걸리는 시간이 오래 걸린다... 어렵다 ㅜㅜ
서브 쿼리를 통해 문제를 해결하는 버릇이 있는데 윈도우 함수를 적극적으로 활용해서 사용하는 방법도 연습해야할 것 같다.
처음에 작성했던 쿼리는 다음과 같다.
SELECT P.MEMBER_NAME, R.REVIEW_TEXT, R.REVIEW_DATE
FROM MEMBER_PROFILE AS P
JOIN MEMBER_REIVEW AS R
WHERE SELECT MAX(B.REVIEW_COUNT)
FROM (SELECT MEMBER_ID, COUNT(MEMBER_ID) AS REVIEW_COUNT
FROM REST_REVIEW
GROUP BY MEMBER_ID) AS B
- JOIN에 ON 절이 없음 → P와 R이 어떻게 매칭되는지 DB가 모름.
- WHERE (SELECT …)처럼 비교 없는 서브쿼리는 불리언이 아니므로 오류.
- “전체 최댓값(MAX)”만 뽑아와도, 각 멤버별 리뷰 수와 비교를 해줘야 “최다 리뷰어”를 걸러낼 수 있음.
- 테이블 명 오타 가능: MEMBER_REIVEW → MEMBER_REVIEW (확인 필요).
- 리뷰를 세는 테이블이 REST_REVIEW인지 MEMBER_REVIEW인지 일관성 필요(아래는 REST_REVIEW에 리뷰가 저장된다고 가정).
WITH cnt AS (
SELECT
MEMBER_ID,
COUNT(*) AS review_count,
DENSE_RANK() OVER (ORDER BY COUNT(*) DESC) AS rnk
FROM REST_REVIEW
GROUP BY MEMBER_ID
)
SELECT
p.MEMBER_NAME,
r.REVIEW_TEXT,
DATE_FORMAT(r.REVIEW_DATE, '%Y-%m-%d') AS REVIEW_DATE
FROM cnt c
JOIN MEMBER_PROFILE p ON p.MEMBER_ID = c.MEMBER_ID
JOIN REST_REVIEW r ON r.MEMBER_ID = c.MEMBER_ID
WHERE c.rnk = 1
ORDER BY r.REVIEW_DATE ASC, r.REVIEW_TEXT ASC;
1. 요구사항 해석
“리뷰를 **가장 많이 작성한 회원(동률 포함)**의 모든 리뷰를 보여라.”
출력: MEMBER_NAME, REVIEW_TEXT, REVIEW_DATE
정렬: REVIEW_DATE 오름차순 → REVIEW_TEXT 오름차순
날짜 포맷: YYYY-MM-DD
2. 관계 파악 (1:N)
MEMBER_PROFILE (회원 1) : REST_REVIEW (리뷰 N)
한 회원이 리뷰를 여러 개 작성할 수 있으므로, 먼저 회원별 리뷰 수를 구해야 함.
3. 집계 대상 확정
리뷰 수는 REST_REVIEW에서 MEMBER_ID 기준 GROUP BY로 계산:
→ 회원별(review_count) = COUNT(*)
4.최댓값 산출(동률 고려)
위 집계 결과들 중 가장 큰 review_count를 구함.
동률이 가능하므로, “= 최댓값” 조건으로 필터해야 최다 리뷰어 전원을 포함할 수 있음.
5. 필터링 전략 선택
집계 서브쿼리를 파생 테이블로 만들고, 그 집계의 최대 review_count와 비교하는 패턴을 사용.
윈도우 함수 DENSE_RANK()로 rnk=1만 남기는 방법도 가능
5. 프로필/리뷰 결합
최다 리뷰어(회원 집계 테이블)를 MEMBER_PROFILE과 MEMBER_ID로 JOIN → MEMBER_NAME 확보.
같은 조건으로 REST_REVIEW와 JOIN → 해당 회원의 모든 리뷰 행 확보.
6. 출력 컬럼 구성 및 포맷, 정렬 규칙 적용
선택 컬럼은 문제 요구대로 MEMBER_NAME, REVIEW_TEXT, REVIEW_DATE.
결과의 REVIEW_DATE에 DATE_FORMAT(..., '%Y-%m-%d') 적용해 출력 형식 통일.
ORDER BY REVIEW_DATE ASC, REVIEW_TEXT ASC