https://school.programmers.co.kr/learn/courses/30/lessons/131124
코드설명
INNER JOIN + SUBQUERY + GROUP BY + HAVING + COUNT(*) 를 활용합니다.
코드
정답코드입니다.
SELECT MP.MEMBER_NAME, RR.REVIEW_TEXT, DATE_FORMAT(RR.REVIEW_DATE, '%Y-%m-%d') AS REVIEW_DATE
FROM MEMBER_PROFILE AS MP
INNER JOIN REST_REVIEW AS RR
ON MP.MEMBER_ID = RR.MEMBER_ID
INNER JOIN (SELECT MEMBER_ID FROM REST_REVIEW GROUP BY MEMBER_ID HAVING COUNT(*) = (SELECT COUNT(*) FROM REST_REVIEW GROUP BY MEMBER_ID ORDER BY COUNT(*) DESC LIMIT 1)) AS RR2
ON RR.MEMBER_ID = RR2.MEMBER_ID
ORDER BY RR.REVIEW_DATE ASC, RR.REVIEW_TEXT ASC
처음에 틀린 접근방법입니다. 이 코드의 경우 INNER JOIN RR이 GROUP BY 로 1개만 나오기에 모든 리뷰 목록을 구하지 못합니다.
-- 코드를 입력하세요
SELECT MP.MEMBER_NAME, RR.REVIEW_TEXT, DATE_FORMAT(RR.REVIEW_DATE, '%Y-%m-%d') AS REVIEW_DATE
FROM MEMBER_PROFILE AS MP
INNER JOIN (SELECT MEMBER_ID, REVIEW_TEXT, REVIEW_DATE FROM REST_REVIEW GROUP BY MEMBER_ID HAVING COUNT(*) = (SELECT COUNT(*) FROM REST_REVIEW GROUP BY MEMBER_ID ORDER BY COUNT(*) DESC LIMIT 1)) AS RR
ON MP.MEMBER_ID = RR.MEMBER_ID
ORDER BY RR.REVIEW_DATE ASC, RR.REVIEW_TEXT ASC
ORACLE
이 쿼리는 반만 정답입니다. 이유는 리뷰를 가장 많이 작성한 사람'들' 이 아닌 가장 많이 작성한 1명만 반환하기 때문입니다.ㅋ
SELECT MP.MEMBER_NAME, RR.REVIEW_TEXT, TO_CHAR(RR.REVIEW_DATE, 'YYYY-MM-DD')
FROM MEMBER_PROFILE MP
INNER JOIN (SELECT MEMBER_ID, REVIEW_TEXT, REVIEW_DATE
FROM REST_REVIEW
WHERE MEMBER_ID = (
SELECT MEMBER_ID
FROM (
SELECT MEMBER_ID
FROM REST_REVIEW
GROUP BY MEMBER_ID
ORDER BY COUNT(*) DESC
) WHERE ROWNUM = 1
) ) RR
ON MP.MEMBER_ID = RR.MEMBER_ID
ORDER BY RR.REVIEW_DATE ASC, RR.REVIEW_TEXT ASC
아래의 INNER JOIN만으로도 처리가 가능하다.사실상 SUBQUERY를 사용하나 INNER JOIN을 사용하나 본질적으로는 같다.
그리고 사실 위의 쿼리보다는 이 쿼리가 더 맞다. 이유는 이 쿼리의 경우 만약 가장 많이 리뷰를 작성한 사람이 3명일경우에도 처리가 가능하다.
SELECT MP.MEMBER_NAME, RR.REVIEW_TEXT, TO_CHAR(RR.REVIEW_DATE, 'YYYY-MM-DD')
FROM MEMBER_PROFILE MP
INNER JOIN (SELECT MEMBER_ID, COUNT(*) AS COUNT
FROM REST_REVIEW
GROUP BY MEMBER_ID) TB1
ON MP.MEMBER_ID = TB1.MEMBER_ID
INNER JOIN ( SELECT MAX(COUNT(*)) AS COUNT
FROM REST_REVIEW
GROUP BY MEMBER_ID ) TB2
ON TB1.COUNT = TB2.COUNT
INNER JOIN REST_REVIEW RR
ON MP.MEMBER_ID = RR.MEMBER_ID
ORDER BY RR.REVIEW_DATE ASC, RR.REVIEW_TEXT ASC
만약 이 위의 4중 JOIN 문의 JOIN을 줄이고 싶다면, MAX(COUNT(*)) 값을 서브쿼리로 구해서 REST_REVIEW 값에 넣어주면 될 것 입니다.
이 쿼리도 INNER JOIN 을 3개하는 대신 2개로 바꾸고 서브쿼리에 값을 넣은것이다.
SELECT MP.MEMBER_NAME, RR.REVIEW_TEXT, TO_CHAR(RR.REVIEW_DATE, 'YYYY-MM-DD')
FROM MEMBER_PROFILE MP
INNER JOIN (SELECT MEMBER_ID, COUNT(*) AS COUNT
FROM REST_REVIEW
GROUP BY MEMBER_ID
HAVING COUNT(*) = (SELECT MAX(COUNT(*)) AS COUNT
FROM REST_REVIEW
GROUP BY MEMBER_ID )) TB1
ON MP.MEMBER_ID = TB1.MEMBER_ID
INNER JOIN REST_REVIEW RR
ON MP.MEMBER_ID = RR.MEMBER_ID
ORDER BY RR.REVIEW_DATE ASC, RR.REVIEW_TEXT ASC