프로그래머스 SQL 문제(3) - 즐겨찾기가 가장 많은 식당 정보 출력하기
https://school.programmers.co.kr/learn/courses/30/lessons/131123
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
-- 음식종류 FOOD_TYPE별 즐겨찾기수가 많은 식당 음식 종류, ID, 식당이름, ..
-- 즉 음식종류로 GROUP BY를 진행해야한다는 의미
-- 음식 정류로 내림차순
SELECT FOOD_TYPE, REST_ID, REST_NAME, FAVORITES
FROM (SELECT RANK()OVER(PARTITION BY FOOD_TYPE ORDER BY FAVORITES DESC) RANK, FOOD_TYPE, REST_ID, REST_NAME, FAVORITES
FROM REST_INFO)
WHERE RANK = 1
ORDER BY FOOD_TYPE DESC;
특정 열에 대해 그룹별로 나누고, 그 그룹의 1순위를 뽑기 위해
-> RANK()OVER(PARTITION BY ~ ORDER BY~) 를 사용
근데 사실 처음 시도했던 건 이렇게 말고 MAX(FAVORITE)를 이용해서 풀어보고 싶었다
GROUP BY FOOD_TYPE을 하고 MAX(FAVORITE)을 사용하면 그룹 별로 FAVORITE이 높은 MAX값만 추출될 것이라고 생각했기 때문이다
해결하기 위해 다시 시도
SELECT FOOD_TYPE, MAX(FAVORITES)
FROM REST_INFO
GROUP BY FOOD_TYPE;
라고 했더니
이런 멀쩡한 값이 추출됐다.. 왜지? 아까 분명 안돼서..
근데 해결해야 할 건 열값이 다른 것도 추출되어야 한다는 사실
-- 들어가야 하는 모든 열을 넣어보자
SELECT FOOD_TYPE, REST_ID, REST_NAME, MAX(FAVORITES)
FROM REST_INFO
GROUP BY FOOD_TYPE, REST_ID, REST_NAME;
아하 이럴 경우, SELECT에 사용된 열들을 모두 GROUP BY 해줘야 하기 때문에 문제가 생긴다
이렇게 말이다
그러면 MAX(FAVORITES)만 추출한 테이블의 값과 같은 값을 출력하도록 하는 식을 써보자
SELECT FOOD_TYPE, REST_ID, REST_NAME, FAVORITES
FROM REST_INFO
WHERE FOOD_TYPE LIKE (SELECT FOOD_TYPE
FROM (SELECT FOOD_TYPE, MAX(FAVORITES) MF
FROM REST_INFO
GROUP BY FOOD_TYPE)) AND
FAVORITES LIKE (SELECT MF
FROM (SELECT FOOD_TYPE, MAX(FAVORITES) MF
FROM REST_INFO
GROUP BY FOOD_TYPE));
ㅋㅋㅋ당연히 오류남.. 오류도 나고 효율도 떨어지는 식이다
오류난 이유는 서브쿼리가 여러 개의 값을 반환하기 때문이다
그러다 새로운 문법을 발견했다
바로 WHERE (열1, 열2) IN (테이블) -> 열1과 열2의 값이 테이블 안에 존재하면 걔만 뽑아내라 라는 것!
지금까지는 WHERE 절에 열1 ~~~ AND 나 OR 열2~~~ 이런 식으로 했는데
해당 열의 값이 테이블 안에 존재할 경우 걔만 뽑아라 가 된다는 것
-- 음식종류 FOOD_TYPE별 즐겨찾기수가 많은 식당 음식 종류, ID, 식당이름, ..
-- 즉 음식종류로 GROUP BY를 진행해야한다는 의미
-- 음식 정류로 내림차순
SELECT FOOD_TYPE, REST_ID, REST_NAME, FAVORITES
FROM REST_INFO
WHERE (FOOD_TYPE, FAVORITES) IN (SELECT
FOOD_TYPE, MAX(FAVORITES) FAVORITES
FROM REST_INFO
GROUP BY FOOD_TYPE)
ORDER BY FOOD_TYPE DESC;
흠! 흥미롭군요..
근데 RANK() OVER() 절에 익숙해지는 게 좋겠다
<LEARNING POINT>
1. 특정 열로 묶어서 걔 안에서 순위를 매기는 경우 RANK()OVER()을 적극 활용하자
ex) 반 별로 가장 높은 성적을 가지고 있는 학생 한명만 추출하자 이런 식
-> 다만 가장 높은 성적을 가지고 있는 학생 한명만 추출하자는 FETCH FIRST ROW ONLY 를 이용하면 됨
-> LIMIT 5 = FETCH FIRST 5 ROW ONLY
2. WHERE (열1, 열2) IN (테이블) -> 열1과 열2의 값이 테이블 안에 존재하면 걔만 뽑아내라