문제 설명
https://school.programmers.co.kr/learn/courses/30/lessons/131124
문제의 조건은 다음과 같다.
- 리뷰를 가장 많이 작성한 회원의 리뷰 조회
- 회원 이름, 리뷰 텍스트, 리뷰 작성일이 출력
- 리뷰 작성일을 기준으로 오름차순, 리뷰 텍스트를 기준으로 오름차순
회원의 정보가 담긴 테이블과 리뷰 정보가 담긴 테이블이 나누어져 있으므로,
풀이 과정은 다음과 같이 이루어진다.
1. 리뷰를 가장 많이 작성한 회원 찾기
2. 그 회원의 이름, 텍스트, 작성일 출력하기
내 풀이
처음 풀이
-- 회원별 리뷰의 개수를 찾는 쿼리
WITH find_reviews AS (
SELECT MEMBER_ID, REVIEW_TEXT, REVIEW_DATE, count(*) as cnt
FROM REST_REVIEW
GROUP BY MEMBER_ID
),
-- 리뷰를 가장 많이 작성한 회원을 찾는 쿼리
find_member AS (
SELECT MEMBER_ID, REVIEW_TEXT, REVIEW_DATE
FROM find_reviews
WHERE cnt IN (SELECT max(cnt) FROM find_reviews)
),
-- 리뷰를 가장 많이 작성한 회원의 정보를 찾는 쿼리
find_member_info AS (
SELECT MEMBER_ID, REVIEW_TEXT, REVIEW_DATE
FROM REST_REVIEW
WHERE MEMBER_ID IN (SELECT MEMBER_ID FROM find_member)
)
-- 회원 이름, 리뷰, 작성 날짜를 찾는 쿼리
SELECT p.MEMBER_NAME
, f.REVIEW_TEXT
, DATE_FORMAT(f.REVIEW_DATE, '%Y-%m-%d') AS REVIEW_DATE
FROM find_member_info f
INNER JOIN MEMBER_PROFILE p
ON f.MEMBER_ID = p.MEMBER_ID
ORDER BY f.REVIEW_DATE, f.REVIEW_TEXT
이 풀이도 정답은 맞긴 하지만,
좀 더 최적화할 수 있을 것 같아 아래와 같이 수정해보았다.
불필요한 정보를 뺀 최적화 쿼리
-- 회원별 리뷰의 개수를 찾는 쿼리
WITH find_reviews AS (
SELECT MEMBER_ID, count(*) as cnt
FROM REST_REVIEW
GROUP BY MEMBER_ID
),
-- 리뷰를 가장 많이 작성한 회원의 정보를 찾는 쿼리
find_member AS (
SELECT MEMBER_ID
FROM find_reviews
WHERE cnt IN (SELECT max(cnt) FROM find_reviews)
)
SELECT p.MEMBER_NAME
, r.REVIEW_TEXT
, DATE_FORMAT(r.REVIEW_DATE, '%Y-%m-%d') AS REVIEW_DATE
FROM REST_REVIEW r
INNER JOIN find_member f
ON r.MEMBER_ID = f.MEMBER_ID
INNER JOIN MEMBER_PROFILE p
ON r.MEMBER_ID = p.MEMBER_ID
ORDER BY r.REVIEW_DATE, r.REVIEW_TEXT
해당 쿼리는 다음과 같이 이루어진다.
1. 고객별 리뷰의 개수 찾기
: 먼저 리뷰 테이블에서 group by를 통해 회원별 리뷰의 개수를 찾고, 이를 CTE로 정의한다.
이 과정에서 바로 max(count(*))를 통해 최대값을 찾고 싶었는데, 이는 불가능하였다.
(이 부분에서 시간이 다소 걸렸다!)
따라서, 회원별 작성한 리뷰의 개수만 cnt 컬럼에 따로 저장한다.
2. 리뷰를 가장 많이 작성한 회원의 정보를 찾는다.
: 앞서 고객별 리뷰의 개수를 찾는 쿼리에서, 최댓값을 찾아 그 회원의 정보를 찾는다.
이 역시 CTE로 정의한다.
3. 해당 회원의 이름, 리뷰, 작성일을 찾는다.
: 이제 리뷰를 가장 많이 작성한 회원의 정보를 찾았기 때문에,
이를 본래 테이블과 join하여 회원의 이름, 리뷰, 작성일을 찾는다.
이 때, 본래 테이블인 member_profile 테이블과 join을 통해 회원의 이름을 찾아야하며,
rest_review 테이블과 join을 통해 review_text, review_date를 찾아야한다.
이상한 점
다소 이상한 점이 있다.
회원별 리뷰의 개수를 찾아보면, 리뷰를 가장 많이 작성한 회원은 중복이 된다.
아래와 같이 member_id별 리뷰의 개수를 찾아보면,
가장 많이 작성한 리뷰의 개수는 3이며,
총 3명의 회원이 3개의 리뷰를 작성하였다.
이를 바탕으로 내가 제출한 결과는 다음과 같다.
총 3명의 회원에 대한 리뷰를 모두 찾아내었다.
이는 분명 정답으로 뜬다!
그러나..
다음과 같이 count(*)에서 LIMIT 1을 통해 간단하게 가장 최상위 회원만 찾아내어도
정답으로 뜬다!
SELECT A.MEMBER_NAME,
B.REVIEW_TEXT,
DATE_FORMAT(B.REVIEW_DATE, "%Y-%m-%d") AS REVIEW_DATE
FROM MEMBER_PROFILE A join REST_REVIEW B
ON A.MEMBER_ID = B.MEMBER_ID
WHERE A.MEMBER_ID = (SELECT MEMBER_ID FROM REST_REVIEW
GROUP BY MEMBER_ID
ORDER BY COUNT(*) DESC LIMIT 1)
ORDER BY REVIEW_DATE asc, REVIEW_TEXT
참 웃긴다:)
'코딩테스트 > SQL' 카테고리의 다른 글
[프로그래머스][MySQL] Lv. 4 식품분류별 가장 비싼 식품의 정보 조회하기 (0) | 2024.07.29 |
---|---|
[프로그래머스][MySQL] Lv. 3 대여 횟수가 많은 자동차들의 월별 대여 횟수 구하기 (0) | 2024.07.25 |
[프로그래머스][MySQL] Lv. 4 FrontEnd 개발자 찾기 (1) | 2024.07.17 |
[프로그래머스][MySQL] Lv. 4 주문량이 많은 아이스크림들 조회하기 (0) | 2024.07.16 |
[프로그래머스][MySQL] Lv. 4 5월 식품들의 총매출 조회하기 (0) | 2024.07.16 |