PS/SQL
[SQL] 즐겨찾기가 가장 많은 식당 정보 출력하기
행복한라이언
2024. 2. 2. 13:55
728x90
반응형
문제링크
https://school.programmers.co.kr/learn/courses/30/lessons/131123
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
1. 핵심
- 음식종류별로 즐겨찾기가 '가장 많은' 식당
- 음식종류별 group by
- 즐겨찾기가 가장 많은
2. 코드(MySQL)
[틀린 코드(에러) 및 이유]
select FOOD_TYPE, REST_ID, REST_NAME, FAVORITES
from REST_INFO
group by FOOD_TYPE
order by FOOD_TYPE desc;
select FOOD_TYPE, REST_ID, REST_NAME, FAVORITES
from REST_INFO
group by FOOD_TYPE
having max(FAVORITES)
order by FOOD_TYPE desc;
- ★ GROUP BY에 정의한 컬럼만 SELECT절에서 그대로 사용할 수 있고, 정의되지 않은 컬럼의 경우에는 반드시 집계함수로 처리를 해줘야한다.
- 그러므로 위의 SQL문에서 FOOD_TYPE을 제외한 나머지 컬럼들은 '그대로' 쓰는 것이 아니라 집계함수를 써서 표현해야한다는 것이다.
- 따라서 저 SQL문은 에러다. 하지만 MySQL에서는 임의로 처리를 해버려서 에러가 발생하지 않는데 다른 DBMS에서는 에러가 발생하는 부분이다.
- ★ Having도 주의하자! GROUP BY이후 행에 대한 필터링을 진행한다. 즉, 집계된 조건을 기반으로 필터링하기 위한 조건이 필요하다! 따라서 'Having 조건식'의 형태이다.
- max(FAVORITES) = FAVORITES 오류가 발생하는 이유는?
- max(FAVORITES)는 집계함수로 특정 행의 FAVORITES)와 직접 비교될 수 없다.
- 밑에 처럼 사용해여한다.
SELECT FOOD_TYPE, MAX(FAVORITES) AS Max_Favorites
FROM REST_INFO
GROUP BY FOOD_TYPE
HAVING MAX(FAVORITES) = 200;
- 따라서, 좋아요가 가장 많은 FOOD_TYPE을 찾기 위해서는 서브쿼리절에서 GROUP BY를 통해서 최대 조회수를 찾고 기존의 테이블과 JOIN하는 방법이 있다.
- 'select FOOD_TYPE, MAX(FAVORITES) AS FAVORITES from REST_INFO group by FOOD_TYPE' SQL문을 보면 group by에서 정의한 FOOD_TYPE만 그대로 사용할 수 있고 다른 컬럼인 FAVORITES는 집계함수를 사용한 것을 볼 수 있다.
select R1.FOOD_TYPE, R1.REST_ID, R1.REST_NAME, R1.FAVORITES
from REST_INFO R1
inner join (
select FOOD_TYPE, MAX(FAVORITES) AS FAVORITES
from REST_INFO
group by FOOD_TYPE) R2 on R1.FOOD_TYPE = R2.FOOD_TYPE AND R1.FAVORITES = R2.FAVORITES
order by R1.FOOD_TYPE desc;
- 윈도우 함수(순위) 활용
- RANK() OVER(PARTITION BY □ ORDER BY □ ) AS □
- ex) 1 2 3 5 6 7 7 7 10위: 동점에 같은 순위 부여 + 동점자 수 만큼 순위 밀림
- DENSE_RANK() OVER(PARTITION BY □ ORDER BY □ ) AS
- ex) 1 2 3 5 6 7 7 7 8위: 동점에 같은 순위 부여 + 같은 순위 부여 후 +1
- ROW_NUMBER() OVER(PARTITION BY □ ORDER BY □) AS □
- ex) 1 2 3 5 6 7 8 9 10위: 동점에 같은 순위 부여하지 않음. 무조건 하나씩 증가
- PARTITION BY - 행을 그룹화하는데 사용
- ORDER BY - 행의 순위를 결정
- RANK() OVER(PARTITION BY □ ORDER BY □ ) AS □
SELECT R.FOOD_TYPE, R.REST_ID, R.REST_NAME, R.FAVORITES
FROM (
SELECT FOOD_TYPE, REST_ID, REST_NAME, FAVORITES,
ROW_NUMBER() OVER (PARTITION BY FOOD_TYPE ORDER BY FAVORITES DESC) AS rn
FROM REST_INFO
) AS R
## 1위 가져오겠다는 의미
WHERE R.rn = 1
ORDER BY R.FOOD_TYPE DESC;
3. 활용예제
SELECT
Food_Type,
Restaurant_Name,
Favorites,
RANK() OVER(PARTITION BY Food_Type ORDER BY Favorites DESC) AS Rank,
DENSE_RANK() OVER(PARTITION BY Food_Type ORDER BY Favorites DESC) AS Dense_Rank,
ROW_NUMBER() OVER(PARTITION BY Food_Type ORDER BY Favorites DESC) AS Row_Number
FROM
Restaurant;
* 참고사이트
https://www.youtube.com/watch?v=WP1E7xlqdzY&t=32s
728x90
반응형