Q. 리뷰를 가장 많이 작성한 회원의 리뷰들을 조회
보자마자 작성한 쿼리. 나름 논리적이지만 내가 봐도 당황스럽다.

SELECT M3.MEMBER_NAME,
R3.REVIEW_TEXT,
DATE_FORMAT(R3.REVIEW_DATE,'%Y-%m-%d') AS REVIEW_DATE
FROM MEMBER_PROFILE M3 JOIN REST_REVIEW R3
ON M3.MEMBER_ID = R3.MEMBER_ID
WHERE M3.MEMBER_ID IN
(
SELECT M2.MEMBER_ID
FROM MEMBER_PROFILE M2 JOIN REST_REVIEW R2
ON M2.MEMBER_ID = R2.MEMBER_ID
GROUP BY 1
HAVING COUNT(R2.review_id) =
(
SELECT MAX(review_cnt)
FROM
(
SELECT M.MEMBER_ID,
COUNT(R.REVIEW_ID) AS review_cnt
FROM MEMBER_PROFILE M JOIN REST_REVIEW R
ON M.MEMBER_ID = R.MEMBER_ID
GROUP BY 1
) a
)
)
ORDER BY 3, 2
" 1. 회원별 리뷰 개수 구하고
2. 그 중 최댓값 구하고
3. 회원별 리뷰 개수가 최댓값과 일치하는 애들 데려와 "
맞긴 맞는데
일을 왜이렇게 어렵게 시키세요 ;;;;;;;;
max 값을 구하는 더 쉬운 방법을 찾아야할 것 같은 느낌.
방법1. ORDER BY ~ LIMIT n ??????
SELECT MEMBER_ID
FROM REST_REVIEW
GROUP BY 1
ORDER BY COUNT(*) DESC
LIMIT 1
"회원별로 리뷰 개수가 가장 많은 애 1명만 데려와"
상위 몇 개 구할 때 LIMIT 쓰니까 여기서도 이렇게 해서 최댓값 구하면 되지 않을까? 싶었지만
최댓값만큼 리뷰를 쓴 사람이 1명이 아닐 수도 있기 때문에 안된다.
방법2. RANK 함수 !!!!!!!!!!!
SELECT MEMBER_ID
FROM
(
SELECT MEMBER_ID,
RANK() OVER (ORDER BY COUNT(*) DESC) AS rnk
FROM REST_REVIEW
GROUP BY 1
) A
WHERE rnk = 1
"회원별 리뷰 개수가 많은 순서대로 순위를 매겼을 때 1등인 애들만 데려와"
RANK는 중복값도 같은 순위를 매기니까 rnk = 1 이라고 해도 여러 명의 데이터가 나올 수 있다는 뜻.
문제에서 조건으로 주어진 '리뷰를 가장 많이 작성한 회원' 을 만족하는 MEMBER_ID 리스트가 나오는 거다.
조건 만들었으니 이제 다시 필요한 애들만 데려오는 메인 쿼리를 작성해보자.
SELECT M.MEMBER_NAME,
R.REVIEW_TEXT,
DATE_FORMAT(R.REVIEW_DATE,'%Y-%m-%d') AS REVIEW_DATE
FROM MEMBER_PROFILE M JOIN REST_REVIEW R
ON M.MEMBER_ID = R.MEMBER_ID
WHERE M.MEMBER_ID IN
(
SELECT MEMBER_ID
FROM
(
SELECT MEMBER_ID,
RANK() OVER (ORDER BY COUNT(*) DESC) AS rnk
FROM REST_REVIEW
GROUP BY 1
) A
WHERE rnk = 1
)
ORDER BY 3,2
처음에는 서브쿼리가 3개였는데 RANK 사용하니 1개로 줄었다. 🫢
회원별 리뷰 개수를 구하고 ➡️ 그 중 최댓값을 구한 다음 ➡️ 회원별 리뷰 개수가 최댓값과 일치하는 조건의 회원을 구하는 3번의 단계가
순위 매기고 ➡️ 그 중 1등인 회원만 구하는 걸로 끝나기 때문 !
window 함수는 복잡한 서브쿼리 계산 없이 간단하게 원하는 조건을 만들어줄 수 있다.
근데 이거보다 더 간단한 방법이 있었다 ,,
같은 팀원 분이 공유해주신 쿼리 !
방법3. RANK 함수 + INNER JOIN 👍🏼👍🏼👍🏼👍🏼👍🏼👍🏼
SELECT m.member_name,
r.review_text,
DATE_FORMAT(r.review_date, '%Y-%m-%d') review_date
FROM member_profile m
INNER JOIN rest_review r
ON m.member_id = r.member_id
INNER JOIN (
SELECT member_id,
RANK() OVER (ORDER BY COUNT(*) DESC) rk
FROM rest_review
GROUP BY member_id
) a
ON m.member_id = a.member_id
WHERE a.rk = 1
ORDER BY review_date, review_text;
위에서는 WHERE 절로 [회원ID가 서브쿼리의 회원 ID에 포함될 때] 라는 조건을 넣어줬는데
그냥 아예 조인을 2번 해버리는 거다.
공유할 수 있는 공통칼럼으로 그 조건을 만들어 줄 수 있으니까 !
그럼 INNER JOIN 이 의미하는 바가 [회원ID가 서브쿼리의 회원 ID에 포함될 때] 라는 조건과 같아지니까 !!
'데이터 분석 > SQL' 카테고리의 다른 글
| [day13] SQLD 헷갈리는 부분 정리 ˚。・゚✧ (0) | 2025.03.01 |
|---|---|
| [day12] with recursive 재귀문 만들기 (0) | 2025.02.28 |
| [day10] operand should contain 1 column(s) (0) | 2025.02.26 |
| [day9] history 리스트에서 특정 날짜 기준으로 대여 가능 여부 확인하기 (0) | 2025.02.25 |
| [day8] 특정 열값이 MAX인 행을 그룹핑하기 (0) | 2025.02.24 |