2024-03-29 [SQL ROW_NUMBER() OVER (PARTITION BY ORDER BY)]
CASE
식당의 정보를 담은 [REST_INFO] 테이블입니다.
REST_ID, REST_NAME, FOOD_TYPE, VIEWS, FAVORITES, PARKING_LOT, ADDRESS, TEL은
식당 ID, 식당 이름, 음식 종류, 조회수, 즐겨찾기수, 주차장 유무, 주소, 전화번호를 의미
문제 : 음식종류 별로 즐겨찾기수가 가장 많은 식당의
음식 종류, ID, 식당 이름, 즐겨찾기수를 조회하는 SQL문을 작성 (결과는 음식 종류를 기준으로 내림차순 정렬)
쉽게 말해 FOOD_TYPE 별 FAVORITES 가장 많은 로우를 조회하는 것인데,
Subquery를 만들어 각 음식 종류 별 즐겨찾기 수가 가장 많은 그룹을 분류해야 하나 싶었다가 어떤 식으로 작성을 해도 지속적으로 출력되지 않아, 답안을 찾아보았다.
ROW_NUMBER
다른 사람들의 풀이 중 가장 쉽게 쿼리를 작성할 수 있는 ROW_NUMBER 함수를 찾아 개념을 찾아보고 적용해 보았다.
- ROW_NUMBER 함수는?
ROW_NUMBER 함수란?
- 각 PARTITION 내에서 ORDER BY절에 의해 정렬된 순서를 기준으로 고유한 값을 반환하는 함수입니다.
- 윈도우 함수(Window Funtion)로 그룹 내 순위 함수입니다.
해당 함수에 대해 알아보면서 RANK 함수도 해당 문제에 동일하게 적용이 가능하겠다 싶어 찾아보니, ROW_NUMBER와 기능적으로 너무 유사하여 각 함수들의 차이점을 추가적으로 찾아보았다.
- RANK 함수
- RANK 함수는 ORDER BY를 포함한 쿼리문에서 특정 항목에 대한 순위를 구하는 함수로, 이 때 특정범위 (PARTITION BY) 내에서 순위를 구할 수도 있고, 전체 데이터에 대한 순위를 구할 수도 있다.
- 동일한 값에 대해서는 동일한 순서를 부여하게 된다.
EX) 동일한 값을 가진 ROW가 1,1로 순서를 부여 받았다면, 다음 ROW는 3으로 순서를 부여
- DENSE_RANK 함수
- 기존 RANK 함수와 다르게 DENSE_RANK 함수는 동일한 순위를 하나의 건수로 취급한다.
EX) 동일한 값을 가진 1,1로 순서를 부여 받았다면, 다음 ROW는 2로 순서를 부여 (동일한 값의 ROW들이 하나의 건수로 취급)
- ROW_NUMBER 함수
- 동일한 값이라도 고유한 순위를 부여
- 동일한 값의 순위를 정해야 할 때 오라클의 경우 ROW ID가 적은 행이 먼저 출력
- 만약 동일 값에 대한 순서까지 관리하고 싶으면 ROW_NUMBER() OVER (ORDER BY SAL DESC, ENAME)을 같이 ORDER BY 절을 이용해 추가적인 정렬 기준을 정의
.
.
.
개념을 짚어보고, 작성해 본 쿼리는 다음과 같다.
SELECT FOOD_TYPE, REST_ID, REST_NAME, FAVORITES
FROM
(
SELECT FOOD_TYPE, REST_ID, REST_NAME, FAVORITES,
ROW_NUMBER() OVER(PARTITION BY FOOD_TYPE ORDER BY FAVORITES DESC) TYPE_FAV_RANK
FROM REST_INFO
) A
WHERE TYPE_FAV_RANK = 1
ORDER BY FOOD_TYPE DESC
- PARTITION BY절을 활용 결과 집합을 파티션으로 분리하는 기능으로, 음식종류 별로 그룹을 나누고, ROW_NUMBER에 필수적으로 활용 해야하는 ORDER BY절을 활용하여 즐겨찾기 순으로 순차를 매겨줘야하나, 많은 순이니 DESC으로 내림차순 정렬
- WHERE 조건문 활용 집합 별 1순위인 로우만 출력될 수 있도록 설정