[LeetCode] 1084. Sales Analysis III
Write a solution to report the products that were only sold in the first quarter of 2019. That is, between 2019-01-01 and 2019-03-31 inclusive. Return the result table in any order.
Table: Product
+--------------+---------+
| Column Name | Type |
+--------------+---------+
| product_id | int |
| product_name | varchar |
| unit_price | int |
+--------------+---------+
Table: Sales
+-------------+---------+
| Column Name | Type |
+-------------+---------+
| seller_id | int |
| product_id | int |
| buyer_id | int |
| sale_date | date |
| quantity | int |
| price | int |
+-------------+---------+
Output:
+-------------+--------------+
| product_id | product_name |
+-------------+--------------+
| 1 | S8 |
+-------------+--------------+
문제 파악
2019년 1분기 (1월~3월)에 팔린 기록이 있는 상품을 필터링하되, 그 외 날짜에는 단 한번도 팔리지 않은 상품의 상품id, 상품명을 출력하는 문제
접근 방법(1차 - 오답)
처음 생각했던 풀이 방법은 1분기 포함된 상품을 먼저 필터링한 후, 그 상품들 중에서 1분기 외에 판매된 상품들의 상품들을 제외하여 출력하자! 였지만 오답이였음. 왜 오답인지 생각해 봤을 때, 이 쿼리는 전체 판매 기록 중 일부만 판단하는 코드가 되어 잘 못된 풀이가 됨.
1. 먼저, s.sale_date BETWEEN '2019-01-01' AND '2019-03-31' 이 부분에서 1분기 이외의 판매 기록은 애초에 조회 대상에서 제외되어버림.
2. 이 상태에서 NOT IN 서브쿼리를 써도 이미 필터링된 행만 보게 되므로 상품이 실제로는 다른 월에도 팔렸어도 1월에만 팔린 것처럼 보이게 되어 잘못된 결과가 나옴.
이 두 과정이 따로 따로 적용될거라고 생각해서 틀리게 된 것 같음
select s.product_id product_id, p.product_name product_name
from product p join sales s on p.product_id=s.product_id
where 1=1
and s.sale_date between '2019-01-01' and '2019-03-31'
and s.product_id not in (select product_id
from sales
where sale_date not between '2019-01-01' and '2019-03-31')
접근 방법(2차 - 정답)
해결 방법으로, 상품 id와 상품명을 기준으로 그룹화하여 상품 각각의 판매 기록 전체를 기준으로 가장 빠른 판매일과 가장 늦은 판매일을 확인한 뒤,그 날짜 범위가 모두 2019년 1분기 사이에 속하는 경우에만 결과로 출력하는 방법으로 풀이
select p.product_id, p.product_name
from Product p join Sales s on p.product_id=s.product_id
group by 1,2
having min(s.sale_date) >= '2019-01-01'
and max(s.sale_date)<='2019-03-31'