[SQL] 그룹별 조건에 맞는 식당 목록 출력하기

Hyunjun Kim·2024년 10월 17일
0

SQL

목록 보기
19/44

문제 설명

다음은 고객의 정보를 담은 MEMBER_PROFILE테이블과 식당의 리뷰 정보를 담은 REST_REVIEW 테이블입니다. MEMBER_PROFILE 테이블은 다음과 같으며 MEMBER_ID, MEMBER_NAME, TLNO, GENDER, DATE_OF_BIRTH는 회원 ID, 회원 이름, 회원 연락처, 성별, 생년월일을 의미합니다.

Column_nameTypeNullable
MEMBER_IDVARCHAR(100)FALSE
MEMBER_NAMEVARCHAR(50)FALSE
TLNOVARCHAR(50)TRUE
GENDERVARCHAR(1)TRUE
DATE_OF_BIRTHDATETRUE

REST_REVIEW 테이블은 다음과 같으며 REVIEW_ID, REST_ID, MEMBER_ID, REVIEW_SCORE, REVIEW_TEXT,REVIEW_DATE는 각각 리뷰 ID, 식당 ID, 회원 ID, 점수, 리뷰 텍스트, 리뷰 작성일을 의미합니다.

Column_nameTypeNullable
REVIEW_IDVARCHAR(10)FALSE
REST_IDVARCHAR(10)TRUE
MEMBER_IDVARCHAR(100)TRUE
REVIEW_SCORENUMBERTRUE
REVIEW_TEXTVARCHAR(1000)TRUE
REVIEW_DATEDATETRUE

문제

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

문제 접근

처음엔 REST_REVIEW 테이블에서 리뷰를 가장 많이 작성한 회원을 찾기 위해서
ID 별(그룹) SELECT COUNT(리뷰 수) 를 했었는데 그렇게 묶는 순간 모든 리뷰들이 묶여서 사용할 수 없게 되는 문제가 있었고

조건절에 서브쿼리를 넣어서 리뷰수가 가장 많았던 ID를 찾아 해당 아이디를 가진 게시글만 조회하도록 코드를 작성해 풀 수 있었다.

문제 풀이

나의 풀이

SELECT m.MEMBER_NAME, r.REVIEW_TEXT, DATE_FORMAT(REVIEW_DATE, "%Y-%m-%d") REVIEW_DATE
FROM (SELECT MEMBER_ID, MEMBER_NAME
FROM MEMBER_PROFILE
WHERE MEMBER_ID = (SELECT MEMBER_ID 
    FROM REST_REVIEW
    GROUP BY MEMBER_ID
    ORDER BY COUNT(*) DESC LIMIT 1) ) m  JOIN
(SELECT REVIEW_TEXT, REVIEW_DATE, MEMBER_ID
 FROM REST_REVIEW ) r
 ON m.MEMBER_ID = r.MEMBER_ID
 ORDER BY REVIEW_DATE, REVIEW_TEXT

정답 공유1 - 리뷰 개수가 가장 많은 사람이 한명일 때.

SELECT c.member_name
     , a.review_text
     , date_format(a.review_date, '%Y-%m-%d')
FROM rest_review a
         INNER JOIN (SELECT member_id
                     FROM rest_review
                     GROUP BY member_id
                     ORDER BY COUNT(*) DESC LIMIT 1) b
                    ON a.member_id = b.member_id
         LEFT JOIN member_profile c ON a.member_id = c.member_id
ORDER BY a.review_date, a.review_text

정답 공유2. - 리뷰 개수가 가장 많은 회원이 2 이상일 때

WITH MAX_MEMBER AS (SELECT MEMBER_ID
FROM REST_REVIEW
GROUP BY MEMBER_ID
HAVING COUNT(*) = (SELECT COUNT(*) AS MAX_COUNT
FROM REST_REVIEW 
GROUP BY MEMBER_ID
ORDER BY COUNT(*) DESC
LIMIT 1)
)
SELECT M.MEMBER_NAME, R.REVIEW_TEXT, DATE_FORMAT(R.REVIEW_DATE,'%Y-%m-%d')
FROM REST_REVIEW R
JOIN MAX_MEMBER MM
ON R.MEMBER_ID = MM.MEMBER_ID
LEFT JOIN MEMBER_PROFILE M
ON R.MEMBER_ID = M.MEMBER_ID
ORDER BY R.REVIEW_DATE, R.REVIEW_TEXT

성율님 정답

SELECT m.member_name, r.review_text,
date_format(r.review_date,'%Y-%m-%d') review_date
FROM member_profile m join rest_review r on m.member_id=r.member_id
join (SELECT m.member_id,
		count(r.member_id)
        FROM member_profile m join rest_review on
        m.member_id = r.member_id
        group by m.member_id
        order by 2 desc
        limit 1) a on r.member_id = a.member_id
order by 3,2

나는 잘 풀었다고 생각했는데 이 쿼리를 보고서 머리를 한 대 얻어 맞은 느낌이었다.
내 쿼리와 이 쿼리의 차이점은 위에 적어놓은 대로 글을 가장 많이 쓴 사람이 한 사람이 아닐 경우에는 해당 사람들의 글들을 전부 가져오도록 sql 쿼리를 작성한 것인데, 나는 이 부분은 고려하지 않고 풀었었다.

아직 left JOIN 개념이 잘 안 잡혀서 다른 사람이 푼 left join 사용구문을
잘 이해하지 못하겠다. 조금 더 정진하도록!

0개의 댓글