Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

63 指定日期的产品价格 #76

Open
astak16 opened this issue Sep 26, 2023 · 0 comments
Open

63 指定日期的产品价格 #76

astak16 opened this issue Sep 26, 2023 · 0 comments
Labels

Comments

@astak16
Copy link
Owner

astak16 commented Sep 26, 2023

题目

题目链接:指定日期的产品价格

编写一个解决方案,找出在 2019-08-16 时全部产品的价格,假设所有产品在修改前的价格都是 10 。

以 任意顺序 返回结果表。

结果格式如下例所示。

输入:
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, change_date) 是此表的主键(具有唯一值的列组合)。
这张表的每一行分别记录了 某产品 在某个日期 更改后 的新价格。

输出:
+------------+-------+
| product_id | price |
+------------+-------+
| 2          | 50    |
| 1          | 35    |
| 3          | 10    |
+------------+-------+
Create table If Not Exists Products (product_id int, new_price int, change_date date);
Truncate table Products;
insert into Products (product_id, new_price, change_date) values ('1', '20', '2019-08-14');
insert into Products (product_id, new_price, change_date) values ('2', '50', '2019-08-14');
insert into Products (product_id, new_price, change_date) values ('1', '30', '2019-08-15');
insert into Products (product_id, new_price, change_date) values ('1', '35', '2019-08-16');
insert into Products (product_id, new_price, change_date) values ('2', '65', '2019-08-17');
insert into Products (product_id, new_price, change_date) values ('3', '20', '2019-08-18');

解析

这题考察的点是如何查出 product_id3 的数据,因为这个产品在 2019-08-16 之前没有修改过价格

方法一

思路:

查询出在 2019-08-16 之前的最新修改过价格的 product_id

如果修改过价,那么 new_price 是有值的

没有修改过价格,那么 new_pricenull,给它赋值为 10

+------------+-------------+
| product_id | new_price   |
+------------+-------------+
| 1          | 35          |
| 2          | 50          |
| 3          | NULL        |
+------------+-------------+

步骤:

  1. 按照 product_id,查询出 2019-08-16 日期之前的最新修改过价格的产品,注意:这里查询不出价格
  2. 使用子查询,根据 product_idchange_date 查询出 product_idnew_price,作为临时表 tmp2
  3. 查询出所有产品的 product_id,作为临时表 tmp1
    • SELECT product_id FROM Products GROUP BY product_id
    • SELECT DISTINCT product_id FROM Products
  4. 左连查询,将 tmp1tmp2 左连,连接条件是 product_id
    • 使用 if 或者 ifnull 判断 new_price 是否为空,如果为空,则使用 10 作为价格
SELECT
   product_id, IF(new_price, new_price, 10) price
FROM (
   SELECT product_id FROM Products GROUP BY product_id
) tmp1
LEFT JOIN (
   SELECT product_id, new_price FROM Products WHERE ( product_id, change_date )
   IN ( SELECT product_id, max(change_date) FROM Products WHERE DATE ( change_date ) <= DATE ( "2019-08-16" ) GROUP BY product_id )
) tmp2 USING ( product_id )

方法二

方法二的思路正好和方法一是相反的

思路:

查询出每个产品在 2019-08-16 之前,最后修改价格的日期,在左连 Products 表,那么 product_id3 的产品就没有价格

+------------+-------------+
| product_id | change_date |
+------------+-------------+
| 1          | 2019-08-16  |
| 2          | 2019-08-14  |
| 3          | NULL        |
+------------+-------------+

步骤:

  1. 按照 product_id 分组,查询出 2019-08-16 之前,最后修改价格的日期,作为临时表 tmp
  2. tmpProducts 左连,连接条件是 product_idchange_date
    • 使用 if 或者 ifnull 判断 new_price 是否为空,如果为空,则使用 10 作为价格
WITH tmp AS (
	SELECT
      product_id, MAX(IF(DATE ( change_date ) <= DATE ( "2019-08-16" ), change_date, NULL)) change_date
   FROM Products GROUP BY product_id
)
SELECT
   product_id, IF(new_price, new_price, 10) price
FROM tmp LEFT JOIN Products USING(product_id, change_date)

方法三

思路:

使用窗口函数,将每个产品按照修改日期进行排序

步骤:

  1. 查询出在 2019-08-16 日期前修改过价格的记录,将大于 2019-08-16 的日期设置为 null,作为临时表 tmp
  2. 使用窗口函数,按照 product_id 分组,按照 change_date 降序排序,作为临时表 tmp2
  3. 查询出 tmp2,筛选出 rk = 1product_idnew_price
    • 使用 if 或者 ifnull 判断 new_price 是否为空,如果为空,则使用 10 作为价格
    • 使用 distinct 去重,可能会有某个产品某天修改多次的记录
SELECT
   DISTINCT product_id, IF(change_date, new_price, 10) price
FROM (
   SELECT
      *, RANK() OVER(PARTITION BY product_id ORDER BY change_date DESC) AS rk
   FROM (
      SELECT product_id, new_price, IF(DATE( change_date ) > DATE( "2019-08-16" ), NULL, change_date) change_date FROM Products
   ) tmp
) tmp2 WHERE rk = 1

相关联的题目

按分类统计薪水

@astak16 astak16 added the 中等 label Sep 26, 2023
@astak16 astak16 changed the title 63 按分类统计薪水 63 指定日期的产品价格 Sep 26, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant