
Lv. 4
GROUP BY JOIN
Summer/Winter Coding(2019)
이 문제는 특별히 두가지 방법으로 풀었다.
따로 여러 방법이 생각나서는 아니고... 사실 풀만하다고 생각했는데 중간에 막혀서 다른 방법을 생각해봤고 이후 원래 방법으로도 풀어냈기 때문이다.
💡 첫번째 방법
NAME의 중복을 제거한다.NAME이 'Milk'와 'Yogurt' 중 하나인 것들을 필터링한다.CART_ID의 수가 2 이상인 것들을 필터링한다.💡 두번째 방법
NAME='Milk'인 CART_ID, NAME='Yogurt'인 CART_ID를 각각 추출한다.CART_ID의 중복을 각각 제거한다.JOIN한다.첫번째 방법에서 1, 2, 3을 모두 진행한 뒤 DISTINCT NAME 컬럼을 선택하지 않기 위해 이 쿼리를 서브쿼리로 하여 다시 CART_ID만 선택하도록 작성했었다.
그리고 에러가 발생했다.
물론 건방진 소리지만 어라?? 내 생각대로면 되어야하는데 왜 안되지?? 하는 생각에 당황했다.
전체 컬럼을 뽑아서 확인해보니 요거트만 3개 산 카트까지 전부 출력하고있었다.
고민하던 중 다른 간단한 풀이가 생각나서 두번째 방법으로 풀게되었다.
근데... 이론상은 맞는데 안된다?
이거 실행순서 때문인가? 하는 생각이 들었다.
MySQL에서 쿼리의 실행 순서는 다음과 같다.

FROM : 테이블을 확인WHERE : 조건 필터링GROUP BY : 그룹화HAVING : 그룹화 조건 필터링SELECT : 컬럼 선택ORDER BY : 정렬내가 생각한대로 흐르려면 GROUP BY는 NAME의 중복이 제거된 뒤 실행되어야한다.
하지만 DISTINCT는 SELECT에 속하므로 GROUP BY와 HAVING이 모두 진행된 뒤 실행된다.
그래서 "우유나 요거트가 2개 이상 담긴 카트 추출 쿼리"가 되고 만 것이다.
이는 서브쿼리에서 1, 2번 까지만 진행하고 3번 GROUP BY와 HAVING을 서브쿼리 밖으로 꺼내주면 해결이 가능하다.
/*
우유와 요거트가 담긴 장바구니
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;
기초적인 부분에서 놓치는게 생길 수 있다는 걸 다시 느껴본 문제였다.