그룹별 조건에 맞는 식당 목록 출력하기
JOIN
그룹별 조건에 맞는 식당 목록 출력하기
문제 설명
다음은 고객의 정보를 담은 MEMBER_PROFILE 테이블과 식당의 리뷰 정보를 담은 REST_REVIEW 테이블입니다.
MEMBER_PROFILE 테이블
Column name | Type | Nullable | Description |
---|---|---|---|
MEMBER_ID | VARCHAR(100) | FALSE | 회원 ID |
MEMBER_NAME | VARCHAR(50) | FALSE | 회원 이름 |
TLNO | VARCHAR(50) | TRUE | 회원 연락처 |
GENDER | VARCHAR(1) | TRUE | 성별 |
DATE_OF_BIRTH | DATE | TRUE | 생년월일 |
REST_REVIEW 테이블
Column name | Type | Nullable | Description |
---|---|---|---|
REVIEW_ID | VARCHAR(10) | FALSE | 리뷰 ID |
REST_ID | VARCHAR(10) | TRUE | 식당 ID |
MEMBER_ID | VARCHAR(100) | TRUE | 회원 ID |
REVIEW_SCORE | NUMBER | TRUE | 리뷰 점수 |
REVIEW_TEXT | VARCHAR(1000) | TRUE | 리뷰 텍스트 |
REVIEW_DATE | DATE | TRUE | 리뷰 작성일 |
문제
MEMBER_PROFILE와 REST_REVIEW 테이블에서 리뷰를 가장 많이 작성한 회원의 리뷰들을 조회하는 SQL문을 작성해주세요. 회원 이름, 리뷰 텍스트, 리뷰 작성일이 출력되도록 작성해주시고, 결과는 리뷰 작성일을 기준으로 오름차순, 리뷰 작성일이 같다면 리뷰 텍스트를 기준으로 오름차순 정렬해주세요. REVIEW_DATE의 데이트 포맷이 예시와 동일해야 정답처리 됩니다. (예시 : YYYY-MM-DD)
풀이 과정
- 조건 확인
MEMBER_ID
기준 리뷰를 가장 많이 작성한 회원의 리뷰 데이터 조회REVIEW_DATE
의 데이트 포맷은 YYYY-MM-DD
- 리뷰를 가장 많이 작성한 회원 찾기
- REST_REVIEW 테이블에서 회원별 리뷰 개수를 그룹화하여, 가장 많은 리뷰를 작성한 회원 찾기
- 이를 위해 GROUP BY
MEMBER_ID
를 사용하여 회원별 리뷰 개수를 계산하고, COUNT(*)로 로 각 회원의 리뷰 개수를 집계 - ORDER BY COUNT(*) DESC로 리뷰 개수가 가장 많은 회원을 찾고, FETCH FIRST 1 ROWS ONLY로 상위 한 명만 선택
- 테이블 결합 (JOIN)
- INNSER JOIN 선택 이유 : 리뷰를 쓴 회원이여야 하므로 두 테이블 모두에 존재하는
MEMBER_ID
여야 하기 때문
- INNSER JOIN 선택 이유 : 리뷰를 쓴 회원이여야 하므로 두 테이블 모두에 존재하는
- 결과 정렬
- 정렬 기준에 따라 ORDER BY로 결과 정렬
- 리뷰 작성일(
REVIEW_DATE
)를 기준으로 오름차순 - 리뷰 작성일이 같다면
REVIEW_TEXT
기준 오름차순
- 리뷰 작성일(
- 정렬 기준에 따라 ORDER BY로 결과 정렬
- 최종 결과 출력
- 최종적으로 회원 이름(
MEMBER_NAME
), 리뷰 텍스트(REVIEW_TEXT
), 리뷰 작성일(REVIEW_DATE
)만 출력 - TO_CHAR(REVIEW_DATE, ‘YYYY-MM-DD’)를 사용하여 날짜를 YYYY-MM-DD 형식의 문자열로 변환
- 최종적으로 회원 이름(
- 교훈
- 서브쿼리 활용해서 특정 조건에 맞는 데이터를 먼저 필터링한 후 메인 쿼리에서 결합하는 것… 자주 쓰임.
- 익숙하지 않은 FETCH FIRST 숫자 ROWS ONLY.. 기존에 쓰던 ROWNUM만이 자꾸 떠오른다…..
정답
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
SELECT
MP.MEMBER_NAME,
RR.REVIEW_TEXT,
TO_CHAR(RR.REVIEW_DATE, 'YYYY-MM-DD') AS REVIEW_DATE
FROM
MEMBER_PROFILE MP
JOIN
REST_REVIEW RR
ON
MP.MEMBER_ID = RR.MEMBER_ID
WHERE
RR.MEMBER_ID = (
SELECT MEMBER_ID
FROM REST_REVIEW
GROUP BY MEMBER_ID
ORDER BY COUNT(*) DESC
FETCH FIRST 1 ROWS ONLY
)
ORDER BY
RR.REVIEW_DATE ASC,
RR.REVIEW_TEXT ASC;
Tip
- 가장 리뷰를 많이 작성한 회원 조회
- 서브쿼리로 가장 리뷰를 많이 작성한 회원의 ID를 찾고, 이를 기반으로 필요한 데이터를 JOIN하여 조회
- GROUP BY
MEMBER_ID
: MEMBER_ID로 그룹화합니다.- ORDER BY COUNT(*) DESC: 리뷰 개수가 많은 순서대로 정렬합니다.
- FETCH FIRST 1 ROWS ONLY: 가장 상위의 한 행만 가져옵니다.
- DATE 타입 형식 맞추기
- TO_CHAR(
컬럼명
, ‘YYYY-MM-DD’) = ‘YYYY-MM-DD’ (VARCHAR 타입으로 변경됨)
SQL Dialect Used: Oracle
개념 확인
- INNER JOIN
- 두 테이블의 공통된 값을 기준으로 데이터를 연결
- 양쪽 테이블 모두에 일치하는 행만 결과에 포함됨
- TO_CHAR 함수
- 날짜 또는 숫자를 문자열 형식으로 변환
- GROUP 함수
- 특정 컬럼 값을 기준으로 데이터를 그룹화하여 집계 계산 수행
- COUNT(*)은 해당 그룹의 모든 행을, COUNT(컬럼명)은 NULL이 아닌 값 개수를 계산
- ORDER BY COUNT() : COUNT로 집계된 값에 따라 결과를 정렬
- FETCH FIRST n ROWS ONLY
- 결과에서 상위 n개의 행만 가져오는 절
- Oracle 12c 이상에서는 이 구문을 사용하며, Oracle 11g 이하에서는 ROWNUM <= 3로 대체할 수 있음
- MYSQL에서는 LIMIT n;
Useful link
This post is licensed under Park Juyoung by the author.