[Programmers/mysql] 62284: 우유와 요거트가 담긴 장바구니 (+ 쿼리의 실행 순서)

songeunm·2024년 9월 12일

PS - sql

목록 보기
13/58
post-thumbnail

문제

Lv. 4
GROUP BY JOIN
Summer/Winter Coding(2019)

문제 흐름

이 문제는 특별히 두가지 방법으로 풀었다.
따로 여러 방법이 생각나서는 아니고... 사실 풀만하다고 생각했는데 중간에 막혀서 다른 방법을 생각해봤고 이후 원래 방법으로도 풀어냈기 때문이다.

💡 첫번째 방법

  1. 전체 데이터에서 NAME의 중복을 제거한다.
  2. 이중에서 NAME이 'Milk'와 'Yogurt' 중 하나인 것들을 필터링한다.
  3. CART_ID의 수가 2 이상인 것들을 필터링한다.

💡 두번째 방법

  1. 전체 데이터에서 NAME='Milk'CART_ID, NAME='Yogurt'CART_ID를 각각 추출한다.
  2. 추출한 CART_ID의 중복을 각각 제거한다.
  3. 두 테이블을 JOIN한다.

첫번째 방법에서 1, 2, 3을 모두 진행한 뒤 DISTINCT NAME 컬럼을 선택하지 않기 위해 이 쿼리를 서브쿼리로 하여 다시 CART_ID만 선택하도록 작성했었다.
그리고 에러가 발생했다.
물론 건방진 소리지만 어라?? 내 생각대로면 되어야하는데 왜 안되지?? 하는 생각에 당황했다.
전체 컬럼을 뽑아서 확인해보니 요거트만 3개 산 카트까지 전부 출력하고있었다.
고민하던 중 다른 간단한 풀이가 생각나서 두번째 방법으로 풀게되었다.

근데... 이론상은 맞는데 안된다?
이거 실행순서 때문인가? 하는 생각이 들었다.

MySQL에서 쿼리의 실행 순서는 다음과 같다.

  1. FROM : 테이블을 확인
  2. WHERE : 조건 필터링
  3. GROUP BY : 그룹화
  4. HAVING : 그룹화 조건 필터링
  5. SELECT : 컬럼 선택
  6. ORDER BY : 정렬

내가 생각한대로 흐르려면 GROUP BYNAME의 중복이 제거된 뒤 실행되어야한다.
하지만 DISTINCTSELECT에 속하므로 GROUP BYHAVING이 모두 진행된 뒤 실행된다.
그래서 "우유나 요거트가 2개 이상 담긴 카트 추출 쿼리"가 되고 만 것이다.

이는 서브쿼리에서 1, 2번 까지만 진행하고 3번 GROUP BYHAVING을 서브쿼리 밖으로 꺼내주면 해결이 가능하다.

코드

/*
우유와 요거트가 담긴 장바구니
Summer/Winter Coding(2019)
GROUP BY, JOIN
*/

-- 방법 1 (오답)
SELECT CART_ID
FROM (
SELECT DISTINCT NAME, CART_ID
FROM CART_PRODUCTS
WHERE NAME IN ('Milk', 'Yogurt')
GROUP BY CART_ID
HAVING COUNT(CART_ID) >= 2
) as T1
ORDER BY CART_ID;

-- 방법 1 (정답)
SELECT CART_ID
from (
SELECT DISTINCT NAME, CART_ID
FROM CART_PRODUCTS
WHERE NAME IN ('Milk', 'Yogurt')
) as T1
GROUP BY CART_ID
HAVING COUNT(CART_ID) >= 2
ORDER BY 1;

-- 방법 2 (정답)
SELECT CART_ID
FROM
    (SELECT DISTINCT CART_ID
    FROM CART_PRODUCTS
    WHERE NAME = 'Milk') T1
JOIN
    (SELECT DISTINCT CART_ID
    FROM CART_PRODUCTS
    WHERE NAME = 'Yogurt') T2
USING (CART_ID)
ORDER BY 1;

마무리

기초적인 부분에서 놓치는게 생길 수 있다는 걸 다시 느껴본 문제였다.

profile
데굴데굴 구르는 개발자 지망생

0개의 댓글