Product Price at a Given Date - LeetCode
주어진 컬럼은 product_id, new_price, chage_date (제품의 가격의 변화가 기록된 테이블)
이걸 가지고 2019-08-16 이라는 특정 날짜의 제품별 가격을 출력하는 문제이다.
뭔가 간단한 거 같은데 해결하는 데 꽤 오랜 시간이 걸렸다.
- 가격이 변화한 경우에만 데이터가 존재
- 가격 변화 전 모든 제품의 가격은 10
[풀이]
-- 1. 출력: product_id, price
-- 2. 필터: 2019-08-16의 가격
-- 3. 정렬: X
WITH sub AS(
SELECT product_id AS pid
,MAX(change_date) AS last_change_date
FROM products
WHERE change_date <= '2019-08-16'
GROUP BY 1
) -- 기준일 전 가격 변동이 없었던 제품은 출력X
SELECT DISTINCT product_id
,IF(last_change_date IS NULL, 10, new_price) AS price
FROM products p
LEFT JOIN sub s ON p.product_id = s.pid
WHERE change_date = last_change_date
OR last_change_date IS NULL
- WITH문으로 기준일 전 가격 변동이 있었던 제품과 변동 날짜 테이블 생성
- 조인 조건에 의해 가격 변동이 없었던 제품은 s.pid와 last_chage_date 값이 NULL
- 기준일 전에 가격 변동이 있었던 제품은 WHERE절 조건에 의해 한번만 출력됨
- 그러나 기준일 전에 변동이 없고 그 후 여러번 변동된 제품은 last_change_date IS NULL 조건에 의해 중복 출력됨.
따라서 DISTINCT를 사용해야 함.
기준일을 변경해도 항상 적용할 수 있는 쿼리를 짜고 싶었다. 효율적인 쿼리인지는 잘 모르겠다..ㅜ
근데 해당 문제는 모든 제품이 무조건 언제가 한번 이상 가격 변동이 있다는 가정이 필요한 것 같다.
가격 변동이 있어야만 products 테이블이 기록될 수 있기 때문
주어진 테이블이 하나여서 가격 변동이 없었다면 해당 제품의 id를 알 수 없고 출력할 수 없으니 말이다.
문제 자체는 짧았는데 쉽지 않았다..
+) 다른 풀이
--다른 풀이 참조
WITH cy AS (
SELECT *
,RANK() OVER (PARTITION BY product_id ORDER BY change_date DESC) AS r
FROM products
WHERE change_date <= '2019-08-16'
)
SELECT product_id
,new_price AS price
FROM cy
WHERE r = 1
UNION
SELECT product_id
,10 AS price
FROM products
WHERE product_id NOT IN (SELECT product_id FROM cy) -- 서브쿼리를 사용해 기준일 전에 변동이 없었던 제품 필터링
- 윈도우 함수 RANK()를 이용해 기준일 전 가격 변동 날짜 순서 생성(최근 변동 순으로)
- r = 1로 마지막 변동 출력
- 서브쿼리를 이용해 기준일 전 변동이 없었던 제품 필터링해서 가격 10으로 출력 후 UNION으로 합치고 마무리
'SQL > LeetCode' 카테고리의 다른 글
| [SQL] LeetCode: 180. Consecutive Numbers (0) | 2024.02.08 |
|---|---|
| [SQL] LeetCode: 610. Triangle Judgement (0) | 2024.02.08 |
| [SQL] LeetCode : 184. Department Highest Salary (0) | 2024.01.31 |
| [SQL] LeetCode: 1789. Primary Department for Each Employee (1) | 2024.01.26 |
| [SQL] LeetCode: 1731. The Number of Employees Which Report to Each Employee (0) | 2024.01.17 |