본문 바로가기

Study/SQL

MySQL | 프로그래머스 | 우유와 요거트가 담긴 장바구니

Question

문제 설명
CART_PRODUCTS 테이블은 장바구니에 담긴 상품 정보를 담은 테이블입니다. CART_PRODUCTS 테이블의 구조는 다음과 같으며, ID, CART_ID, NAME, PRICE는 각각 테이블의 아이디, 장바구니의 아이디, 상품 종류, 가격을 나타냅니다.

NAME  TYPE
ID  INT
CART_ID  INT
NAME  VARCHAR
PRICE  INT

데이터 분석 팀에서는 우유(Milk)와 요거트(Yogurt)를 동시에 구입한 장바구니가 있는지 알아보려 합니다. 우유와 요거트를 동시에 구입한 장바구니의 아이디를 조회하는 SQL 문을 작성해주세요. 이때 결과는 장바구니의 아이디 순으로 나와야 합니다.

 

예시
예를 들어 CART_PRODUCTS 테이블이 다음과 같다면

CART_PRODUCTS 테이블

ID CART_ID NAME PRICE
1630 83 Cereal 3980
1631 83 Multipurpose Supply 3900
5491 286 Yogurt 2980
5504 286 Milk 1880
8435 448 Milk 1880
8437 448 Yogurt 2980
8438 448 Tea 11000
20236 1034 Yogurt 2980
20237 1034 Butter 4890
  • 83번 장바구니에는 Milk와 Yogurt가 모두 없습니다.
  • 286번 장바구니에는 Milk와 Yogurt가 모두 있습니다.
  • 448번 장바구니에는 Milk와 Yogurt가 모두 있습니다.
  • 1034번 장바구니에는 Milk는 없고 Yogurt만 있습니다.

따라서 SQL 문을 실행하면 다음과 같이 나와야 합니다.

CART_ID
286
448

 

Solve

글을 작성하게 된 이유, 다양한 풀이법이 있다.

-- 풀이 1
SELECT y.cart_id 
from (select cart_id from cart_products where name = 'Yogurt') as y
	join (select cart_id from cart_products where name = 'Milk') as m
            on y.cart_id = m.cart_id
group by y.cart_id
order by y.cart_id

풀이 1. 요거트를 구매한 아이디의 테이블과, 우유를 구매한 테이블을 inner join 하는 풀이법

 

-- 풀이 2 : cross join
SELECT distinct P1.CART_ID
    FROM CART_PRODUCTS P1
    CROSS JOIN CART_PRODUCTS P2
    ON P1.CART_ID = P2.CART_ID AND P1.NAME = 'Milk' AND P2.NAME = 'Yogurt'​

풀이 2. 같은 테이블을 cross join, 이 때 한 쪽은 요거트를 구입하고 다른 한 쪽은 우유를 구입

첫번째 풀이법과 같은 맥략이지만 inner join이 아닌 cross join을 사용했다.

 

-- 풀이 3 : self join
SELECT distinct o.CART_ID
from CART_PRODUCTS o, CART_PRODUCTS n
where o.CART_ID = n.CART_ID and o.NAME = "Milk" and n.NAME = "Yogurt" 
order by o.CART_ID

풀이 3. cross join과 비슷한 맥락의 self join

 

-- 풀이 4 : group_concat
select cart_id
from cart_products
group by cart_id 
having group_concat(name) like '%milk%'
	and group_concat(name) like '%yogurt%'
order by cart_id

풀이 4. group_concat 으로 그룹별 조건을 만들어 엮어주는 풀이법

사실 group_concat은 사용해 본 경험이 없어서 용례를 더 찾아보고 정리해 볼 예정이다.

 

-- 풀이 5 : in, distinct
SELECT CART_ID
FROM CART_PRODUCTS
WHERE NAME IN ('Milk', 'Yogurt')
GROUP BY CART_ID
HAVING COUNT(DISTINCT(NAME)) >= 2
ORDER BY CART_ID

풀이 5. having 절에 집계함수를 이용

우유 혹은 요거트를 산 데이터들 중, cart_id로 그룹핑했을 때, name이 다른 것이 2개 이상일 때

 

첫 접근은 풀이 1번으로 접근했는데 뭔가 더 간결한 코드는 없을까 고민했다.

풀이 5번은 disscussion에서 찾은 코드인데 가장 간결하고 재미있던 코드였다.


Source

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

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr