[LeetCode] 1158. Market Analysis 1 - IFNULL() : 특정 컬럼값이 null일 때 0으로 표시하기
문제 링크 : https://leetcode.com/problems/market-analysis-i
문제설명
- Users, Orders, Items 3개의 테이블이 있다. (이커머스 업계에서 볼 수 있는 전형적인 테이블 관계.)
- 이때 user는 buyer가 될 수도 있고 seller가 될 수도 있다.
- [user, join date, 주문 수]를 추출하는데, user가 buyer로써 2019년에 주문한 건에 대해서 추출한다.
솔루션
맨 처음에 풀었던 코드.
SELECT u.user_id AS buyer_id
,u.join_date AS join_date
,CASE WHEN oc.order_cnt IS NULL THEN 0 ELSE oc.order_cnt END AS orders_in_2019
FROM Users u
LEFT JOIN (
SELECT buyer_id
,COUNT(order_id) AS order_cnt
FROM Orders
WHERE YEAR(order_date) = 2019
GROUP BY buyer_id
) AS oc ON u.user_id = oc.buyer_id
ORDER BY u.user_id ASC
- 어쨌든 추출해야 하는 건, user별 주문 건수이다. 그러므로 Items 테이블은 볼 필요가 없다.
- [user, join_date, 주문수]를 추출해야 한다. user, join_date는 Users 테이블에, 주문수는 Orders 테이블에 있다. 그러므로 Users & Orders 두 테이블의 관계를 이용해서 풀어야 한다. (JOIN)
- 먼저 Orders 테이블에서 buyer_id별로 2019년에 주문한 주문건수를 구한다. -> oc라고 별칭을 지정해준다.
- 회원가입을 하더라도 주문을 안하는 경우가 있으므로, Users 테이블을 기준으로 LEFT JOIN을 하여 Orders 테이블과 연결한다. 이때 조건은 u.user_id와 oc,buyer_id.
- join한 테이블에서 문제에서 요구한 컬럼들을 추출한다.
CASE WHEN ~ orders_in_2019 코드에서 CASE문을 쓴 이유는
LEFT JOIN을 했을 때, id가 일치하는 행이 없으면 오른쪽 테이블(여기선 oc)에 null이 붙기 때문이다.
일단 답은 맞았는데...
저 코드를 좀 더 간결하게 만들 수 있는 방법이 없을까? 생각했다.
찾아본 결과, IFNULL()함수를 사용하면 되었다.
두번째 코드.
SELECT u.user_id AS buyer_id
,u.join_date AS join_date
,IFNULL(oc.order_cnt, 0) AS orders_in_2019
FROM Users u
LEFT JOIN (
SELECT buyer_id
,COUNT(order_id) AS order_cnt
FROM Orders
WHERE YEAR(order_date) = 2019
GROUP BY buyer_id
) AS oc ON u.user_id = oc.buyer_id
ORDER BY u.user_id ASC
oc.order_cnt가 NULL값을 가진다면, 0으로 써준다.
그리고 좀 더 가독성있게 만들 수 없을까?
고민하다가 WITH문을 써서 한번 더 정리하였다.
세 번째 코드.
WITH order_cnts AS (
SELECT buyer_id
,COUNT(order_id) AS order_cnt
FROM Orders
WHERE YEAR(order_date) = 2019
GROUP BY buyer_id
)
SELECT u.user_id AS buyer_id
,u.join_date AS join_date
,IFNULL(oc.order_cnt, 0) AS orders_in_2019
FROM Users u
LEFT JOIN order_cnts AS oc ON u.user_id = oc.buyer_id
ORDER BY u.user_id ASC
확실히 WITH절을 쓰니 깔끔하게 정리되었다.