본문 바로가기
PS/SQL

[SQL] 즐겨찾기가 가장 많은 식당 정보 출력하기

by 행복한라이언 2024. 2. 2.
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;
728x90
  • 윈도우 함수(순위) 활용
    • 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 - 행의 순위를 결정
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://wikidocs.net/132723

https://www.youtube.com/watch?v=WP1E7xlqdzY&t=32s

 

728x90
반응형