https://school.programmers.co.kr/learn/courses/30/lessons/62284#qna
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
데이터 분석 팀에서는 우유(Milk)와 요거트(Yogurt)를 동시에 구입한 장바구니가 있는지 알아보려 합니다. 우유와 요거트를 동시에 구입한 장바구니의 아이디를 조회하는 SQL 문을 작성해주세요. 이때 결과는 장바구니의 아이디 순으로 나와야 합니다.
예시
예를 들어 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 |
정답
SELECT DISTINCT(A.CART_ID) FROM CART_PRODUCTS AS A
RIGHT JOIN (SELECT CART_ID, GROUP_CONCAT(DISTINCT NAME) AS NAME FROM CART_PRODUCTS
WHERE NAME LIKE ('%Milk%') OR NAME LIKE ('%Yogurt%')
GROUP BY CART_ID
HAVING NAME LIKE ('%,%')) AS B
ON A.CART_ID=B.CART_ID
ORDER BY CART_ID
GROUP_CONCAT은 그룹별로 컬럼 데이터(문자열)를 묶을때 사용하는 함수이다.
예시를 들면
animal | name |
monkey | Lo |
monkey | Jay |
monkey | Jayce |
elephant | pink |
elephant | Tayo |
elephant | K |
위와 같이 그룹(컬럼)에 따라 데이터가 있는 상황에서,
아래와 같이 그룹별로 문자열을 묶어서 출력할 때 쓰이는 함수이다.
animal | name |
elephant | K,pink,Tayo |
monkey | Jay,Jayce,Lo |
위 정답코드 B테이블의 HAVING절 이전까지의 코드는 다음과 같다.
CART_ID | NAME |
286 | Milk,Yogurt |
287 | Milk |
448 | Milk,Yogurt |
578 | Milk,Yogurt |
636 | Milk |
789 | Yogurt |
830 | Yogurt |
977 | Milk,Yogurt |
996 | Milk |
1034 | Yogurt |
1048 | Milk,Yogurt |
위 문제는 우유와 요거트를 동시에 구매한 카드를 찾는 문제이다. 필자는 이 조건을 만족하는 행만을 추출하는 법을
HAVING NAME LIKE ('%,%')을 이용해 해결했다. 그 결과는 다음과 같다.
CART_ID | NAME |
286 | Milk,Yogurt |
448 | Milk,Yogurt |
578 | Milk,Yogurt |
977 | Milk,Yogurt |
1048 | Milk,Yogurt |
문제의 조건을 만족하는 카드 아이디를 찾았고 RIGHT JOIN을 이용해 최종적으로 해결했다.
하지만 필자가 작성한 코드는 매우 복잡한 코드이다.
모범답안
SELECT CART_ID
FROM CART_PRODUCTS
WHERE NAME IN ('Milk', 'Yogurt')
GROUP BY CART_ID
HAVING COUNT(DISTINCT(NAME)) >= 2
ORDER BY CART_ID
다음과 같은 간단한 코드로 풀 수 있는 문제이다.
HAVING절 이전까지의 코드를 NAME열을 추가해 실행한 결과는 다음과 같다.
CART_ID | NAME |
286 | Yogurt |
287 | Milk |
448 | Milk |
578 | Milk |
636 | Milk |
789 | Yogurt |
830 | Yogurt |
977 | Milk |
996 | Milk |
1034 | Yogurt |
1048 | Yogurt |
필자가 위에서 구한 결과와 동일한 카드 아이디이다. 이를 HAVING COUNT(DISTINCT(NAME)) >= 2를 이용해 쉽게 구하였다.
이 문제는 GROUP_CONCAT같은 어려운 함수를 이용하지 않고도 기본에 충실해 풀 수 있는 문제였다.
'SQL' 카테고리의 다른 글
년, 월, 성별 별로 상품을 구매한 회원수 구하기 문제 (0) | 2023.01.04 |
---|---|
WHERE 논리 연산자 응용 (0) | 2023.01.03 |
서브퀴리 응용(2) (0) | 2023.01.01 |
서브쿼리 응용 (0) | 2022.12.30 |
JOIN, GROUP BY를 동시에 사용하는 경우 (0) | 2022.12.29 |