코딩 테스트 연습/[프로그래머스][리트코드] MySQL

[LV.5] JOIN > 그룹별 조건에 맞는 식당 목록 출력하기 ⭐️

duswjd_data 2025. 7. 11. 15:49

문제

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

 

프로그래머스

SW개발자를 위한 평가, 교육의 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr


문제 설명

  • MEMBER_PROFILE와 REST_REVIEW 테이블에서 리뷰를 가장 많이 작성한 회원의 리뷰들을 조회하는 SQL문을 작성
  • 회원 이름, 리뷰 텍스트, 리뷰 작성일이 출력되도록 작성
  • 결과는 리뷰 작성일을 기준으로 오름차순, 리뷰 작성일이 같다면 리뷰 텍스트를 기준으로 오름차순 정렬
  • 주의사항) REVIEW_DATE의 데이트 포맷이 예시와 동일해야 정답처리

정답 코드1 (성공. 효율 개선 필요)

SELECT SUB.MEMBER_NAME,
       R.REVIEW_TEXT,
       DATE_FORMAT(R.REVIEW_DATE, '%Y-%m-%d') AS REVIEW_DATE
FROM REST_REVIEW R,
     (SELECT M.MEMBER_ID,
             M.MEMBER_NAME
      FROM MEMBER_PROFILE M JOIN REST_REVIEW R ON M.MEMBER_ID = R.MEMBER_ID
      GROUP BY M.MEMBER_ID, M.MEMBER_NAME
      HAVING COUNT(R.REVIEW_ID) = (SELECT MAX(REVIEW_COUNT)
                                   FROM (SELECT COUNT(REVIEW_ID) AS REVIEW_COUNT
                                         FROM REST_REVIEW
                                         GROUP BY MEMBER_ID) C)) SUB
WHERE SUB.MEMBER_ID = R.MEMBER_ID
ORDER BY R.REVIEW_DATE, R.REVIEW_TEXT

정답 코드2

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 RR.MEMBER_ID = MP.MEMBER_ID
WHERE 
    RR.MEMBER_ID IN (
        SELECT MEMBER_ID
        FROM REST_REVIEW
        GROUP BY MEMBER_ID
        HAVING COUNT(*) = (
            SELECT MAX(REVIEW_COUNT)
            FROM (
                SELECT COUNT(*) AS REVIEW_COUNT
                FROM REST_REVIEW
                GROUP BY MEMBER_ID
            ) AS COUNT_TABLE
        )
    )
ORDER BY 
    RR.REVIEW_DATE ASC,
    RR.REVIEW_TEXT ASC

코드 설명

  • 서브쿼리 구조:
    • COUNT_TABLE은 MEMBER_ID별 리뷰 개수를 집계
    • 그 중 MAX(REVIEW_COUNT)를 찾아
    • HAVING COUNT(*) = MAX(REVIEW_COUNT) 조건에 해당하는 회원만 선택
  • IN 절 사용:
    • 최다 리뷰 회원이 여러 명일 경우 모두 선택 가능
  • JOIN을 통해 해당 회원들의 REVIEW_TEXT, REVIEW_DATE, MEMBER_NAME을 추출
  • 정렬 조건 충족:
    • 날짜 오름차순 → 텍스트 오름차순

정답 코드3 (CTE 사용)

WITH REVIEW_COUNT AS (
    SELECT 
        MEMBER_ID, 
        COUNT(*) AS REVIEW_CNT
    FROM REST_REVIEW
    GROUP BY MEMBER_ID
),
MAX_REVIEWERS AS (
    SELECT 
        MEMBER_ID
    FROM REVIEW_COUNT
    WHERE REVIEW_CNT = (
        SELECT MAX(REVIEW_CNT) FROM REVIEW_COUNT
    )
)
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 RR.MEMBER_ID = MP.MEMBER_ID
JOIN MAX_REVIEWERS MR ON RR.MEMBER_ID = MR.MEMBER_ID
ORDER BY RR.REVIEW_DATE ASC, RR.REVIEW_TEXT ASC

코드 설명

  • 1단계: 각 회원별 리뷰 수 집계 (REVIEW_COUNT)
WITH REVIEW_COUNT AS (
    SELECT 
        MEMBER_ID, 
        COUNT(*) AS REVIEW_CNT
    FROM REST_REVIEW
    GROUP BY MEMBER_ID
)
  • 목적: REST_REVIEW 테이블에서 MEMBER_ID별로 몇 건의 리뷰를 남겼는지 계산
  • COUNT(*) AS REVIEW_CNT: 리뷰 개수를 세어 REVIEW_CNT라는 이름으로 저장
  • REVIEW_COUNT는 회원별 리뷰 수를 담고 있는 임시 테이블(CTE) 역할
  • 2단계: 최다 리뷰 회원만 필터링 (MAX_REVIEWERS)
MAX_REVIEWERS AS (
    SELECT 
        MEMBER_ID
    FROM REVIEW_COUNT
    WHERE REVIEW_CNT = (
        SELECT MAX(REVIEW_CNT) FROM REVIEW_COUNT
    )
)
  • 목적: REVIEW_COUNT에서 리뷰 수가 가장 많은 회원(MEMBER_ID)만 추출
  • MAX(REVIEW_CNT): 전체 회원 중 최대 리뷰 수
  • WHERE REVIEW_CNT = MAX(...): 최대 리뷰 수를 가진 회원 필터링 (1명 또는 여러 명 가능)
  • 3단계: 최다 리뷰 회원의 리뷰 정보 조회
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 RR.MEMBER_ID = MP.MEMBER_ID
JOIN MAX_REVIEWERS MR ON RR.MEMBER_ID = MR.MEMBER_ID
ORDER BY RR.REVIEW_DATE ASC, RR.REVIEW_TEXT ASC