프로그래머스 SQL 고득점 Kit - 5월 식품들의 총매출 조회하기

Jinyoung Cheon·2025년 8월 14일
0

코딩테스트

목록 보기
18/25

프로그래머스 SQL 고득점 Kit
https://school.programmers.co.kr/learn/challenges?tab=sql_practice_kit

JOIN

problem

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

code

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;

note

슬슬 한 문제 풀때 걸리는 시간이 오래 걸린다... 어렵다 ㅜㅜ
서브 쿼리를 통해 문제를 해결하는 버릇이 있는데 윈도우 함수를 적극적으로 활용해서 사용하는 방법도 연습해야할 것 같다.

처음에 작성했던 쿼리는 다음과 같다.

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에 리뷰가 저장된다고 가정).

가독성·성능 모두 깔끔. 집계+순위까지 한 번에 처리 - gpt 도움

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
profile
데이터를 향해, 한 걸음씩 천천히.

0개의 댓글