SQL/문제풀이

[LeetCode] average-selling-price 📌

응엉잉 2024. 3. 5. 15:02

https://leetcode.com/problems/average-selling-price/submissions/1194313569/?envType=study-plan-v2&envId=top-sql-50

 

Average Selling Price - LeetCode

Can you solve this real interview question? Average Selling Price - Table: Prices +---------------+---------+ | Column Name | Type | +---------------+---------+ | product_id | int | | start_date | date | | end_date | date | | price | int | +---------------

leetcode.com

SELECT product_id,
    COALESCE(ROUND(SUM(units * temp) / SUM(CASE WHEN temp !=0 THEN units ELSE 0 END), 2), 0) AS average_price
FROM (
    SELECT p.product_id,
        u.units,
        CASE WHEN u.purchase_date <= p.end_date AND u.purchase_date >= p.start_date THEN p.price 
            ELSE 0 END AS temp
    FROM Prices p
        LEFT JOIN UnitsSold u ON p.product_id = u.product_id
) AS a
GROUP BY product_id

1. JOIN 할 때 Prices를 기준으로 JOIN해야 판매량이 없는 물건까지 같이 출력 가능

2. 조건을 만족할 때 가격을 가져오고, 조건을 만족하지 않는 경우 0을 가져오게끔 CASE문을 작성

3.FROM절 서브쿼리를 이용

4. 분모에서 실제 판매된 수량만큼을 가져오기 위해 temp가 0이 아닌 경우만 수량을 더하도록 CASE문을 작성

5. ROUND를 통해 문제에서 원하는 조건 달성

6. COALESCE를 통해 NULL 대신 0이 나오게 처리

 

그치만 너무 비효율적이죠?

Solution을 봐보겠습니다

 

1. 깔끔하게 JOIN하기

SELECT *
FROM Prices p
    LEFT JOIN UnitsSold u ON p.product_id = u.product_id 
        AND u.purchase_date BETWEEN p.start_date AND p.end_date

ON을 사용해 JOIN의 기준이 될 column을 명시해주고

BETWEEN을 이용해 날짜 조건을 만족하는 경우 UnitsSold의 row들이 갖다붙을 수 있게끔 작성

 

2. IFNULL 함수를 이용해서 NULL인 경우를 처리

SELECT p.product_id,
    IFNULL(ROUND(SUM(price * units) / SUM(units), 2), 0) AS average_price
FROM Prices p
    LEFT JOIN UnitsSold u ON p.product_id = u.product_id 
        AND u.purchase_date BETWEEN p.start_date AND p.end_date
GROUP BY p.product_id