題目會給我們一張Products資料表。裡面分別有product_id、new_price、change_date等欄位。其中(product_id, change_date)是這張資料表的複合主鍵Primary key。
所有商品預設都是10元。之後若有更新,則以新價格為主。
要求我們找出每樣商品,在2019-08-16這天所登記的販售價格。
輸出答案時,順序不拘。
Table: Products
+---------------+---------+
| Column Name | Type |
+---------------+---------+
| product_id | int |
| new_price | int |
| change_date | date |
+---------------+---------+
(product_id, change_date) is the primary key (combination of columns with unique values) of this table.
Each row of this table indicates that the price of some product was changed to a new price at some date.
所有商品預設都是10元。
之後若有更新,則以新價格為主。
這題的考點主要在於把題目中的價格欄位的OR運算,轉成等價的SQL查詢語法 UNION。
為什麼這麼說呢?
要求我們找出每樣商品,在2019-08-16這天所登記的販售價格。
因為2019-08-16這天的商品價格可以分成兩種情況討論
第一種情況: 商品價格在2019-08-16這天或者之前有更新過,那當然以新的價格為準。
第二種情況: 商品價格在2019-08-16之後才更新,那就返回10元的預設價格。
第一種情況: 商品價格在2019-08-16這天或者之前有更新過,那當然以新的價格為準。
# Find the price of product updated not later than "2019-08-16"
SELECT p.product_id, p.new_price AS "price"
FROM Products p
WHERE (p.product_id, p.change_date) IN (
SELECT product_id, MAX(change_date)
FROM Products
WHERE change_date <= "2019-08-16"
GROUP BY product_id
)
UNION 聯集
第二種情況: 商品價格在2019-08-16之後才更新,那就返回10元的預設價格。
SELECT product_id, 10
FROM Products
GROUP BY product_id
HAVING MIN(change_date) > "2019-08-16";
# Find the price of product updated not later than "2019-08-16"
SELECT p.product_id, p.new_price AS "price"
FROM Products p
WHERE (p.product_id, p.change_date) IN (
SELECT product_id, MAX(change_date)
FROM Products
WHERE change_date <= "2019-08-16"
GROUP BY product_id
)
UNION
# It is $10 by default for those price of product updated later than "2019-08-16"
SELECT product_id, 10
FROM Products
GROUP BY product_id
HAVING MIN(change_date) > "2019-08-16";
當原本的要求 滿足條件1 OR 滿足條件2 很難在一次SQL內寫完時,可以先拆解,再取對應等價的邏輯操作。
因為這題是 OR,對應到的SQL查詢結果合併的語法就是UNION,取聯集。
Reference:
[1] MySQL by subquery as well as UNION [w/ Comment] - Product Price at a Given Date - LeetCode