[MySQL][Lv. 4] 서울에 위치한 식당 목록 출력하기 ✨

드코미·2025년 5월 3일
post-thumbnail

1. 풀이

내 풀이

SELECT 
    A.REST_ID, 
    A.REST_NAME, 
    A.FOOD_TYPE, 
    A.FAVORITES, 
    A.ADDRESS, 
    ROUND(AVG(REVIEW_SCORE), 2) AS SCORE
FROM REST_INFO A
JOIN REST_REVIEW B
    ON A.REST_ID = B.REST_ID
WHERE ADDRESS LIKE "서울%"
GROUP BY A.REST_ID
ORDER BY SCORE DESC, FAVORITES DESC;

다른 사람의 코드 [출처 링크]

SELECT
    I.REST_ID
    , I.REST_NAME
    , I.FOOD_TYPE
    , I.FAVORITES
    , I.ADDRESS
    , ROUND(AVG(R.REVIEW_SCORE), 2) AS SCORE
FROM 
    REST_INFO AS I
    JOIN REST_REVIEW AS R
    ON I.REST_ID = R.REST_ID
WHERE ADDRESS LIKE '서울%'
GROUP BY 1, 2, 3, 4, 5
ORDER BY SCORE DESC, FAVORITES DESC;

1-1. GROUP BY 1, 2, 3, 4, 5 이거 뭐지..?

나는 그냥 GROUP BY A.REST_ID 이렇게 ID 기준으로만 GROUP BY를 진행했는데, 다른 사람의 풀이를 보니 GROUP BY 1, 2, 3, 4, 5이렇게 생소한 표현을 써서 궁금증이 생겼다.

✔️ SQL 표준(ANSI SQL)의 규칙

SELECT에 있는 모든 컬럼 중,
집계 함수(AVG(), SUM(), COUNT() 등) 안 들어간 컬럼은
👉 GROUP BY에 무조건 써야 함!

예를 들어,

SELECT 고객명, 제품, SUM(가격)
FROM 주문
GROUP BY 고객명;
  • 고객명: GROUP BY에 명시했음 → OK!
  • 제품: 집계함수 쓴 것도 아닌데, GROUP BY에 없네? → 오류
  • SUM(가격): 집계함수 썼으니, GROUP BY에 쓸 필요 없음!

✔️ 그런데, 그걸 지키지 않은 내 코드는 도대체 왜 정답으로 인정된거지..?

MySQL은 기본 설정에서 좀 느슨하게 군다.
그래서 굳이 비집계 컬럼을 명시적으로 GROUP BY에 적어주지 않았어도 오류가 발생하지 않는다.

단, 이건 MySQL 한정 유연성이다.
PostgreSQL, Oracle등은 명시적으로 모든 비집계 컬럼을 GROUP BY에 써야 오류가 발생하지 않는다.

✔️ 그러면 숫자가 의미하는 바가 뭔데?

숫자는 SELECT절에서 몇 번째 컬럼인지를 가리키는 번호다.

SELECT
    A.REST_ID,         -- ← 1번째 컬럼
    A.REST_NAME,       -- ← 2번째 컬럼
    A.FOOD_TYPE,       -- ← 3번째 컬럼
    A.FAVORITES,       -- ← 4번째 컬럼
    A.ADDRESS,         -- ← 5번째 컬럼
    ROUND(AVG(...))    -- ← 6번째 (집계함수니까 제외)

→ 이때 GROUP BY 1, 2, 3, 4, 5
= GROUP BY A.REST_ID, A.REST_NAME, A.FOOD_TYPE, A.FAVORITES, A.ADDRESS 와 똑같아!

✔️ 이해했어.. 그런데 나는 오직 REST_ID 기준으로만 GROUP을 묶고 싶은데, GROUP BY 1, 2, 3, 4, 5 이렇게 써버리면 그룹 묶는 기준이 여러개가 되는거 아니야? 그게 말이 되나?

자 우선 결론만 말하자면,
GROUP BY 1, 2, 3, 4, 5 이렇게 써버리면
1번부터 5번까지 컬럼의 "전체 조합이 완전히 같은 행끼리" 그룹을 묶는 거야!

해당 문제의 경우 결국 JOIN을 했을 때, 1번부터 5번 컬럼까지 당연히 같아지거든? 예를 들어보자.

SELECT 
    A.REST_ID, 
    A.REST_NAME, 
    A.FOOD_TYPE, 
    A.FAVORITES, 
    A.ADDRESS,
    B.REVIEW_SCORE AS SCORE
    -- ROUND(AVG(REVIEW_SCORE), 2) AS SCORE
FROM REST_INFO A
JOIN REST_REVIEW B
    ON A.REST_ID = B.REST_ID
WHERE ADDRESS LIKE "서울%"
-- GROUP BY A.REST_ID
ORDER BY REST_ID;

위의 코드는 정답 코드에서 GROUP BY를 하기 전 코드인데,
보면 GROUP BY하기 전에 이미 컬럼 1부터 5까지 값이 같게 조인되는 걸 확인할 수 있다.

그룹을 묶는 기준이 여러 개인 것이 아니라, 지정한 컬럼들의 값이 모두 같은 행들끼리 하나의 그룹이 되는 것이다.

MySQL이 알아서 유연하게 도와주기 때문에 이렇게 정확하게 안적어도 작동이 잘 되지만, 정확한 방식을 위해서는 GROUP BY 1, 2, 3, 4, 5처럼 적는 것이 더 옳은 방식이다.

profile
할 수 있다!!!

0개의 댓글