SQL

프로그래머스 SQL 문제(3) - 즐겨찾기가 가장 많은 식당 정보 출력하기

김랑해 2023. 8. 2. 21:56

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의 값이 테이블 안에 존재하면 걔만 뽑아내라