일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 히트맵
- SQL
- 데이터 분석
- da
- data analyst
- 시각화
- SQLD
- cross join
- 최종 프로젝트
- 클러스터링
- 태블로
- 기초프로젝트
- 크롤링
- 기초통계
- lambda
- 머신러닝
- 팀프로젝트
- 프롬프트 엔지니어링
- 서브쿼리
- Python
- 프로젝트
- If
- 군집화
- pandas
- streamlit
- jd
- 전처리
- 데이터분석
- Chat GPT
- GA4
- Today
- Total
세조목
SQL 예제 정리('그룹별 조건에 맞는 식당 목록 출력하기')(24.05.05) 본문
https://school.programmers.co.kr/learn/courses/30/lessons/131124
리뷰를 가장 많이 작성한 회원의 이름, 리뷰 텍스트, 리뷰 작성일을 출력하는 것이 이번 문제의 요구사항입니다.
우선 제가 작성한 쿼리 먼저 보여드리겠습니다.
SELECT MP.MEMBER_NAME,
RR.REVIEW_TEXT,
DATE_FORMAT(RR.REVIEW_DATE, '%Y-%m-%d') REVIEW_DATE
FROM MEMBER_PROFILE MP RIGHT JOIN REST_REVIEW RR ON MP.MEMBER_ID=RR.MEMBER_ID
WHERE MP.MEMBER_ID IN (
SELECT B.MEMBER_ID
FROM
(
SELECT A.MEMBER_ID, RANK() OVER(ORDER BY A.CNT_REVIEW DESC) RANKING
FROM
(
SELECT MP.MEMBER_ID,
COUNT(*) CNT_REVIEW
FROM MEMBER_PROFILE MP RIGHT JOIN REST_REVIEW RR ON MP.MEMBER_ID=RR.MEMBER_ID
GROUP BY MP.MEMBER_ID
) A
) B
WHERE B.RANKING = 1
)
ORDER BY REVIEW_DATE, RR.REVIEW_TEXT;
뭐가 좀 많이 복잡하긴한데
- 총 두 개의 서브 쿼리를 활용하여 리슈 수가 가장 많은 멤버를 필터링해서
- 해당 멤버들의 정보들을 본 쿼리에서 출력하게끔 작성된 쿼리입니다.
하나씩 뜯어보겠습니다.
SELECT A.MEMBER_ID, RANK() OVER(ORDER BY A.CNT_REVIEW DESC) RANKING
FROM
(
SELECT MP.MEMBER_ID,
COUNT(*) CNT_REVIEW
FROM MEMBER_PROFILE MP RIGHT JOIN REST_REVIEW RR ON MP.MEMBER_ID=RR.MEMBER_ID
GROUP BY MP.MEMBER_ID
) A
가장 안쪽에 있는 서브쿼리입니다.
여기서는 MEMBER_ID별 리뷰 수를 COUNTING한 후
바깥 쿼리에서 리뷰 수 기준 RANK를 매깁니다.
SELECT B.MEMBER_ID
FROM
(
SELECT A.MEMBER_ID, RANK() OVER(ORDER BY A.CNT_REVIEW DESC) RANKING
FROM
(
SELECT MP.MEMBER_ID,
COUNT(*) CNT_REVIEW
FROM MEMBER_PROFILE MP RIGHT JOIN REST_REVIEW RR ON MP.MEMBER_ID=RR.MEMBER_ID
GROUP BY MP.MEMBER_ID
) A
) B
WHERE B.RANKING = 1
RANK를 매기는 서브쿼리를 다시 한 번 더 서브쿼리로 하는
쿼리문을 작성합니다.
여기서는 단순하게 RANK가 1인 MEMEBER_ID만 뽑아냅니다.
SELECT MP.MEMBER_NAME,
RR.REVIEW_TEXT,
DATE_FORMAT(RR.REVIEW_DATE, '%Y-%m-%d') REVIEW_DATE
FROM MEMBER_PROFILE MP RIGHT JOIN REST_REVIEW RR ON MP.MEMBER_ID=RR.MEMBER_ID
WHERE MP.MEMBER_ID IN (
SELECT B.MEMBER_ID
FROM
(
SELECT A.MEMBER_ID, RANK() OVER(ORDER BY A.CNT_REVIEW DESC) RANKING
FROM
(
SELECT MP.MEMBER_ID,
COUNT(*) CNT_REVIEW
FROM MEMBER_PROFILE MP RIGHT JOIN REST_REVIEW RR ON MP.MEMBER_ID=RR.MEMBER_ID
GROUP BY MP.MEMBER_ID
) A
) B
WHERE B.RANKING = 1
)
ORDER BY REVIEW_DATE, RR.REVIEW_TEXT;
RANK가 1인 MEMBER_ID만 뽑아내는 쿼리문을
본 쿼리의 WHERE 절에 넣어준 후
SELECT 절에 문제에서 요구한 MEMBER_NAME, REVIEW_TEXT, REVIEW_DATE를 적어준 후,
마지막으로 REVIEW_DATE와 REVIEW_TEXT를 기준으로 정렬해줍니다.
이 쿼리의 경우 이전에 작성한 쿼리문을 보지 않고 새롭게 작성한 쿼리문인데요,
예전에 작성한 쿼리문을 확인해보니 훨씬 간단했습니다.
SELECT MP.MEMBER_NAME,
RR.REVIEW_TEXT,
DATE_FORMAT(RR.REVIEW_DATE, '%Y-%m-%d') REVIEW_DATE
FROM MEMBER_PROFILE MP JOIN REST_REVIEW RR ON MP.MEMBER_ID = RR.MEMBER_ID
WHERE MP.MEMBER_ID =
(
SELECT MEMBER_ID
FROM REST_REVIEW
GROUP BY MEMBER_ID
ORDER BY COUNT(*) DESC
LIMIT 1
)
ORDER BY REVIEW_DATE, RR.REVIEW_TEXT
첫 번째 쿼리와 이 쿼리의 차이점은 뭘까요?
두 번째 쿼리는 조건에 해당하는 MEMBER들 중 한 명의 리뷰들만을 출력하는 쿼리입니다.
SELECT MEMBER_ID
FROM REST_REVIEW
GROUP BY MEMBER_ID
ORDER BY COUNT(*) DESC
LIMIT 1
두 번째 쿼리의 서브쿼리를 보시면 '개수'를 기준으로 정렬 후 LIMIT 1을 걸어버립니다.
이렇게 되면 리뷰 수가 동일하더라도 가장 위에 출력되는 MEMBER_ID 하나만 WHERE절에 들어가게 되죠.
PROGRAMMERS에서 두 결과값 모두 정답 처리를 하니 어떤 쿼리를 사용해도 상관은 없을 것 같습니다.
어짜피 쿼리 작성 로직 자체는 동일하니까요.
'데이터 분석 공부 > SQL' 카테고리의 다른 글
SQL 예제 정리('입양 시각 구하기(2)')(24.05.08) (2) | 2024.05.08 |
---|---|
SQL 예제 정리('대여 횟수가 많은 자동차들의 월별 대여 횟수 구하기')(24.05.06) (0) | 2024.05.06 |
SQL 예제 정리('주문량이 많은 아이스크림들 조회하기')(24.05.04) (0) | 2024.05.04 |
SQL 예제 정리('우유와 요거트가 담긴 장바구니')(24.05.03) (0) | 2024.05.03 |
SQL 예제 정리('자동차 대여 기록에서 대여 중/대여 가능 여부 구분하기') (0) | 2024.05.02 |