블로그를 이전 중이라 완료되기 전까지는 벨로그에 작성할 계획입니다.
이후 모든 글은 https://weekwith.me 에 작성 예정이니 다른 글이 궁금하시다면 해당 링크를 통해 방문해주세요.본 글은 [ LeetCode ] 2362. Generate the Invoice를 풀고 작성한 글입니다.
Table: Products
+-------------+------+
| Column Name | Type |
+-------------+------+
| product_id | int |
| price | int |
+-------------+------+
product_id is the primary key for this table.
Each row in this table shows the ID of a product and the price of one unit.
Table: Purchases
+-------------+------+
| Column Name | Type |
+-------------+------+
| invoice_id | int |
| product_id | int |
| quantity | int |
+-------------+------+
(invoice_id, product_id) is the primary key for this table.
Each row in this table shows the quantity ordered from one product in an invoice.
Write an SQL query to show the details of the invoice with the highest price. If two or more invoices have the same price, return the details of the one with the smallest invoice_id
.
Return the result table in any order.
결국 invoice_id
별 가격의 합계의 순위를 구해야 하고 합계를 구하기 이전의 상세 내역을 출력해야 하기 때문에 각 invoice_id
별로 Product
테이블을 JOIN
하여 구한 가격 테이블이 중복된다.
따라서 해당 중복되는 테이블을 공통 테이블 표현식(CTE_Common Table Expression)을 사용해서 효율적으로 사용한다.
다양한 풀이 방식이 있을 수 있으나 SUM()
윈도우 함수(Window Function)을 사용한 다음 WHERE
구에 해당 필드를 기준으로 내림차순 정렬하고 invoice_id
기준으로 오름차순 정렬한 뒤 LIMIT
구의 값을 1
로 지정해서 반환되는 invoice_id
를 조건으로 넘겼다.
접근법을 토대로 문제를 해결하면 아래와 같다.
WITH cte (invoice_id, product_id, quantity, price, price_sum) AS (
SELECT
invoice_id,
Purchases.product_id,
quantity,
quantity * price AS price,
SUM(quantity * price) OVER(PARTITION BY invoice_id) AS price_sum
FROM Purchases
JOIN Products
USING (product_id)
)
SELECT
product_id,
quantity,
price
FROM cte
WHERE invoice_id = (
SELECT invoice_id
FROM cte
ORDER BY price_sum DESC, invoice_id ASC
LIMIT 1
);