[SQL] 'GROUP BY' 동작 방식 (프로그래머스 SQL.GROUP BY - 즐겨찾기가 가장 많은 식당 정보)

유네스코d·2023년 4월 14일

DB

목록 보기
3/3

https://school.programmers.co.kr/learn/courses/30/lessons/131123


프로그래머스에서 위 SQL 문제를 푸는 도중 문제가 발생했다...

SELECT FOOD_TYPE, REST_ID, REST_NAME, MAX(FAVORITES) FAVORITES
FROM REST_INFO
GROUP BY FOOD_TYPE
ORDER BY FOOD_TYPE DESC;

쿼리를 이렇게 작성했는데 FOOD_TYPE 카테고리 별로 MAX값이 잘 나오지 않은 것.
뭐가 문제인가 찾아보니 GROUP BY 절의 동작 방식의 이해가 부족했다


GROUP BY를 사용하면 그룹 별로 가장 상단에 있는 데이터들을 임의로 가져온다.

+-----------+---------+-------------+-----------+
| FOOD_TYPE | REST_ID | REST_NAME	| FAVORITES |
+-----------+---------+-------------+-----------+
| 일식    	| 00002   | 하이가쯔네	| 112		|
| 일식    	| 00023   | 싹쓰리 		| 42		|
| 일식    	| 00005   | 코슌스		| 123		|
| 일식    	| 00004   | 스시사카우스	| 230		|
+-----------+---------+-------------+-----------+

예를 들어, FOOD_TYPE이 일식인 데이터들이 위와 같을 때, 내가 작성했던 쿼리를 적용한다면

+-----------+---------+-------------+-----------+
| FOOD_TYPE | REST_ID | REST_NAME	| FAVORITES |
+-----------+---------+-------------+-----------+
| 일식    	| 00002   | 하이가쯔네	| 230		|
| 일식    	| 00023   | 싹쓰리 		| 230		|
| 일식    	| 00005   | 코슌스		| 230		|
| 일식    	| 00004   | 스시사카우스	| 230		|
+-----------+---------+-------------+-----------+

SQL 내부적으로 이렇게 FAVORITES를 전체적으로 MAX값으로 적용하여 맨 위에 있는 컬럼을 가져오게 된다.
따라서 FAVORITES은 원하는 값이 맞고 FOOD_TYPE도 그룹화하여 전부 동일하므로 문제가 없지만, REST_ID, REST_NAME 은 다른 데이터의 값으로 나오게 되는 것이다.



SELECT FOOD_TYPE, REST_ID, REST_NAME, FAVORITES
FROM REST_INFO
GROUP BY FOOD_TYPE
HAVING FAVORITES = MAX(FAVORITES)
ORDER BY FOOD_TYPE DESC;

이 SQL문을 실행하면 문제가 되는 일식 카테고리 자체가 출력이 되지 않는데,
GROUP BY로 카테고리별 맨 첫번째 데이터들을 가져온 후에 HAVING이 실행되기 때문에
가져온 맨 첫번째 데이터가 일식 카테고리의 MAX값이 아니라 출력이 되지 않은 것 같다.



# 1
SELECT A.FOOD_TYPE, A.REST_ID, A.REST_NAME, A.FAVORITES
FROM REST_INFO A, (SELECT MAX(FAVORITES) MAX 
                   FROM REST_INFO 
                   GROUP BY FOOD_TYPE) B
WHERE A.FAVORITES = B.MAX
GROUP BY FOOD_TYPE
ORDER BY FOOD_TYPE DESC;


# 2
SELECT FOOD_TYPE, REST_ID, REST_NAME, FAVORITES
FROM REST_INFO
WHERE FAVORITES IN (SELECT MAX(FAVORITES)
                    FROM REST_INFO 
                    GROUP BY FOOD_TYPE)
GROUP BY FOOD_TYPE
ORDER BY FOOD_TYPE DESC;

이를 해결하기 위해 서브쿼리를 사용하여
1. B 테이블에 FOOD_TYPE 별로 FAVORITES의 MAX값들을 가져와서
2. A 테이블에서 FAVORITES로 해당 MAX값을 가진 데이터를 가져오고
3. FOOD_TYPE 별로 그룹화하여 정렬한 후 출력해주었다
(1, 2번 둘 다 같은 로직이다)

profile
yune's coding

0개의 댓글