Summer/Winter Coding(2019) 문제, 오류 해결🌞


✔️ 문제 설명

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

NAME TYPE
ID INT
CART_ID INT
NAME VARCHAR
PRICE INT

문제

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


✔️ 문제 풀이

(1) 코드 작성

SELECT CART_ID
FROM (SELECT CART_ID, GROUP_CONCAT(NAME) AS NAME
      FROM CART_PRODUCTS
      WHERE NAME LIKE "Milk" OR NAME LIKE "Yogurt"
      GROUP BY CART_ID) AS C
WHERE NAME LIKE "%Milk%" AND NAME LIKE "%Yogurt%"
ORDER BY CART_ID # 넣지않아도 정답처리 

(2) 코드 리뷰 및 회고

  • 문제는 유저의 장바구니에 요거트와 우유가 들어가있는 경우를 불러오는 것이다.
  • CART_PRODUCTS 테이블에는 한 장바구니 ID에 들어가있는 품목이 행으로 구성되어 있다.(아래와 같음)

CART_PRODUCTS 테이블 구조

ID CART_ID NAME PRICE
101 00101 Milk 1500
102 00101 Yogurt 4400
301 00103 Milk 1500
302 00103 Milk 1500
303 00103 SODA 3000
  • 요거트와 우유 두 품목이 모두 포함된 장바구니 데이터를 불러와야하기 때문에 FROM으로 테이블을 불러올 때, SELECT-FROM-WHERE-GROUP BY 구문으로 테이블을 조금 변경하여 가져왔다.
  • 변경 사항은 WHERE문에 우유 또는 요거트가 포함된 것을 불러오고 장바구니 아이디로 그룹화하였다.
  • 이렇게 하면 장바구니별로 우유 또는 요거트가 하나라도 포함된 장바구니 ID를 불러올 수 있다. 그리고 GROUP_CONCAT 으로 장바구니 ID별 품목을 ,을 구분자로 묶어주었다.
  • 마지막으로 전체 품목(GROUP_CONCAT으로 묶은 NAME)에 요거트와 우유가 모두 되어야 한다는 조건을 WHERE에 추가했다.

💡 AND가 아닌 OR을 사용한 이유

FROM (SELECT CART_ID, GROUP_CONCAT(NAME) AS NAME
      FROM CART_PRODUCTS
      WHERE NAME LIKE "Milk" OR NAME LIKE "Yogurt"
      GROUP BY CART_ID) AS C

정답 코드에서 FROM으로 테이블을 조금 수정하여 가져올 때, WHERE문에 AND가 아닌 OR을 불러온 이유는 아래와 같다.

  • raw 데이터 구조를 보면 장바구니에 포함된 항목들이 하나의 행(raw)로 구성된다. 즉, NAME(품목)을 AND로 불러온다면 아무 데이터도 불러올 수 없다.(아래와 같음)

CART_PRODUCTS 테이블 구조

ID CART_ID NAME PRICE
101 00101 Milk 1500
102 00101 Yogurt 4400
301 00103 Milk 1500
302 00103 Milk 1500
303 00103 SODA 3000
-- OR로 불러올 경우
SELECT CART_ID
FROM CART_PRODUCTS
WHERE NAME LIKE "Milk" OR NAME LIKE "Yogurt"
ID CART_ID NAME PRICE
101 00101 Milk 1500
102 00101 Yogurt 4400
301 00103 Milk 1500
302 00103 Milk 1500
-- AND로 불러올 경우
SELECT CART_ID
FROM CART_PRODUCTS
WHERE NAME LIKE "Milk" AND NAME LIKE "Yogurt"
ID CART_ID NAME PRICE
       
  • 위와 같은 이유로 AND가 아닌 OR를 사용했다.

🌞 에러사항 공유

SELECT CART_ID
FROM (SELECT CART_ID, GROUP_CONCAT(NAME) AS NAME
      FROM CART_PRODUCTS
      WHERE NAME LIKE "Milk" OR NAME LIKE "Yogurt"
      GROUP BY CART_ID)

SQL 실행 중 오류가 발생하였습니다.
Every derived table must have its own alias

  • 위와 같은 메시지가 발생하는 이유는 서브쿼리에 Alias를 주지 않았기 때문이다.
  • 처음 오류 메시지를 보았을 때 서브쿼리를 불러올 수 없는건가? 생각했지만 MySQL에선 Alias를 줘야 불러올 수 있다고 한다!(오라클에서는 X)
  • Python, Pandas로 데이터 프레임을 만들고 또 데이터 프레임을 다른 변수에 저장하여 활용할 때 copy 함수를 사용하라는 warning message가 뜰 때가 있는데 그거와 비슷하다는 생각이 들었다.
  • 기존의 테이블을 수정하여 새로운 df로 활용할 때, Alias(별칭)을 꼭 주자!
SELECT CART_ID
FROM (SELECT CART_ID, GROUP_CONCAT(NAME) AS NAME
      FROM CART_PRODUCTS
      WHERE NAME LIKE "Milk" OR NAME LIKE "Yogurt"
      GROUP BY CART_ID) AS C # AS 없이 C라고만 작성해도 

Note. 에러가 발생한 코드를 수정하면 위와 같다!(별칭 추가)


👩🏻‍💻개인 공부 기록용 블로그입니다
오류나 틀린 부분이 있을 경우 댓글 혹은 메일로 따끔하게 지적해주시면 감사하겠습니다.

댓글남기기