传送门:1164. 指定日期的产品价格
题目
产品数据表: Products
±--------------±--------+
| Column Name | Type |
±--------------±--------+
| product_id | int |
| new_price | int |
| change_date | date |
±--------------±--------+
(product_id, change_date) 是此表的主键(具有唯一值的列组合)。
这张表的每一行分别记录了 某产品 在某个日期 更改后 的新价格。
一开始,所有产品价格都为 10。
编写一个解决方案,找出在 2019-08-16 所有产品的价格。
以 任意顺序 返回结果表。
结果格式如下例所示。
示例 1:
输入:
Products 表:
±-----------±----------±------------+
| product_id | new_price | change_date |
±-----------±----------±------------+
| 1 | 20 | 2019-08-14 |
| 2 | 50 | 2019-08-14 |
| 1 | 30 | 2019-08-15 |
| 1 | 35 | 2019-08-16 |
| 2 | 65 | 2019-08-17 |
| 3 | 20 | 2019-08-18 |
±-----------±----------±------------+
输出:
±-----------±------+
| product_id | price |
±-----------±------+
| 2 | 50 |
| 1 | 35 |
| 3 | 10 |
±-----------±------+
解析
这题最容易想到的是用UNION,不用UNION会很难做。首先通过观察表格不难看出当最小日期大于8.16时,价格肯定是10,所以第一个子查询就是查询产品表,对产品id分组,筛选最小日期大于2019.8.16的记录,返回产品id和价格,其中价格字段为10,别名price。其次,当最小日期小于等于8.16时,最大日期对应的价格即所求,所以第二个子查询需要用嵌套子查询,具体来说,先查询产品表,过滤出日期<=2019.8.16的记录,再对产品id分组求最大日期,返回产品id和最大日期,作为一张表,再查询该表,但这里需要使用类似“(产品id,日期)in子查询”的语法,Oracle不支持,由于本人用的是Oracle,这里将该表和产品表做关联,连接条件为两表产品id相等,产品表日期=子查询返回的最大日期,然后返回产品id和价格,最后用union连接两表即可。注意字符串转日期不同数据库实现不同,由于本人用的Oracle,故使用Oracle的方式,即“date日期字符串”。
代码(Oracle)
select product_id,10 as price
from Products
group by product_id
having min(change_date)>date'2019-08-16'
union
select p.product_id,p.new_price as price
from Products p
join(select product_id,max(change_date)as max_date
from Products
where change_date<=date'2019-08-16'
group by product_id)t
on p.product_id=t.product_id and p.change_date=t.max_date;