본문 바로가기
자격증 공부/PCSQL

[PCSQL] 우유와 요거트가 담긴 장바구니 (MySQL)

by ohback1 2025. 10. 15.

우유와 요거트가 담긴 장바구니 Lv.4

이 문제는 Lv.4 치고 어려운 문제는 아니지만, SUM()이나 MAX() 함수를 사용하여 간단하게 푸는 방법이 있길래 내가 풀었던 방식과 더불어 3가지의 다른 풀이를 정리해봤다. 

 

프로그래머스

SW개발자를 위한 평가, 교육의 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr


풀이1. SELF JOIN (내가 푼 방식)

SELECT DISTINCT a.CART_ID
FROM CART_PRODUCTS a
JOIN CART_PRODUCTS b
  ON a.CART_ID = b.CART_ID
WHERE a.NAME = 'Milk' AND b.NAME = 'Yogurt'
ORDER BY a.CART_ID;

 

  • 행 단위로 JOIN + 조건으로 필터링
  • 같은 CART_ID를 가진 Milk 행과 Yogurt 행이 모두 존재해야 선택
  • 같은 CART_ID가 여러 행으로 JOIN될 수 있으므로 DISTINCT로 중복 제거

 

 

풀이2. MAX 활용

SELECT CART_ID
FROM CART_PRODUCTS
GROUP BY CART_ID
HAVING MAX(NAME = 'Milk') AND MAX(NAME = 'Yogurt')
ORDER BY CART_ID;
  • NAME = 'Milk'는 boolean 조건, TRUE → 1, FALSE → 0로 반환됨
  • MAX(NAME='Milk') → 1 (그룹 안에서 가장 큰 값)
  • MAX(NAME='Yogurt') → 1 (그룹 안에서 가장 큰 값)
  • 그룹 내에 Milk가 존재하면 1, 없으면 0

→ 즉, 위 식은 비교 연산자(=, <, >, <> 등)를 사용하면 자동으로 boolean 값이 생성되고, 그 값은 메모리 상에서 임시 숫자 0/1로 저장되어, 다른 연산(집계 함수, SUM, MAX 등)에 바로 사용되기에 가능한 쿼리이다.

더 자세히 설명을 위해 아래와 같은 테이블이 있다고 가정해보자.

CART_PRODUCTS 테이블

| CART_ID | NAME    |
|---------|---------|
| 1       | Milk    |
| 1       | Yogurt  |
| 1       | Bread   |
| 2       | Milk    |
| 2       | Bread   |
| 3       | Yogurt  |
| 3       | Bread   |


위 테이블을 대상으로 아래 쿼리를 실행하면 다음과 결과가 출력되는데,

SELECT CART_ID, NAME, NAME='Milk' AS is_milk
FROM CART_PRODUCTS;

 

CART_ID NAME is_milk
1 Milk 1
1 Yogurt 0
1 Bread 0
2 Milk 1
2 Bread 0
3 Yogurt 0
3 Bread 0

이 결과는 비교 연산자를 이용하여 is_milk 라는 새로운 컬럼을 생성했을 때, 값이 1, 0로 이루어짐을 보여준다.
여기에 MAX()를 적용하면 아래와 같은 결과가 나온다.

SELECT CART_ID, MAX(NAME='Milk') AS has_milk
FROM CART_PRODUCTS
GROUP BY CART_ID;

 

CART_ID has_milk
1 1
2 1
3 0

이를 통해 각 CART_ID 그룹 안에서 1이 하나라도 있으면 MAX → 1, 없으면 0 으로 반환된다는 것을 알 수 있다.

 

풀이3. SUM 활용 (MAX와 유사한 방법)

SELECT CART_ID
FROM CART_PRODUCTS
GROUP BY CART_ID
HAVING SUM(NAME = 'Milk') > 0 AND SUM(NAME = 'Yogurt') > 0
ORDER BY CART_ID;

 

  • NAME='Milk' → boolean 조건, TRUE → 1, FALSE → 0
  • SUM(NAME='Milk') → 그룹 안에서 1들의 합계
  • SUM(NAME='Yogurt') → 그룹 안에서 1들의 합계
  • SUM(NAME='Milk') > 0 → Milk가 최소 1개 존재하면 TRUE
  • SUM(NAME='Yogurt') > 0 → Yogurt가 최소 1개 존재하면 TRUE
  • HAVING SUM(NAME='Milk')>0 AND SUM(NAME='Yogurt')>0 → 둘 다 존재해야 선택

 

SUM()은 MAX()와 마찬가지로 비교 연산자를 통한 불리언 처리를 활용하는 방식이지만 한가지 큰 차이점이 있다.

SELECT CART_ID, SUM(NAME='Milk') AS milk_count
FROM CART_PRODUCTS
GROUP BY CART_ID;

 

CART_ID milk_count
1 1
2 1
3 0

여기서 MAX와의 큰 차이점은, SUM은 1들의 합계를 보여주기 때문에 존재 개수까지 확인 가능하다는 점이다.