【发布时间】:2021-01-07 14:39:10
【问题描述】:
我有一个表格来存储从给定日期开始的sku 的价格:start_date。对于sku 的新价格,此表中可能有多个条目,新的start_date。从添加新价格之日起,每个新条目都会覆盖上一组行中的价格。
表结构是这样的:
sku_id | start_date | price
100 | "2020-01-10" | 100
100 | "2020-01-20" | 200
100 | "2020-01-30" | 300
有了这些条目,10th Jan、21st Jan 和 31st Jan 的价格将分别显示为 100、200 和 300。
现在,如果我们在此表中输入另一个条目,开始日期为1st Jan,价格为500。然后,直到覆盖所有这 3 个价格。然后,之前获取的所有 3 个日期的价格现在将变为 500。
sku_id | start_date | price
100 | "2020-01-10" | 100
100 | "2020-01-20" | 200
100 | "2020-01-30" | 300
100 | "2020-01-01" | 500 -> This row overrides prices of all 3 rows before it. Since start date `2020-01-01` is less then all their start date.
鉴于这个表结构,这是我的要求:
我想获取所有仍处于活动状态的记录(这意味着它们不会被任何新创建的行完全覆盖)。我想到了使用 LEAD 函数,它可以让我得到每一行的 end_date。
SELECT sku_id, start_date, price,
LEAD(start_date, 1) OVER (
PARTITION BY sku_id ORDER BY created_at
) - INTERVAL '1 day' AS end_date
FROM rate;
这个查询给了我这个结果:
sku_id | start_date | price | end_date
100 | "2020-01-10" | 100 | "2020-01-19"
100 | "2020-01-20" | 200 | "2020-01-29"
100 | "2020-01-30" | 300 | "2019-12-31"
100 | "2020-01-01" | 500 |
在此之后,我需要一些查询,它可以拒绝第 1、2 和 3 行,因为它们的开始日期小于第 3 行的结束日期。这是我无法理解如何实现的。
如果问题的标题没有意义,真的很抱歉,因为我想不出要给出什么问题的标题。
我采用的另一种方法是按降序保持加载记录。然后使用该记录作为游标,获取 start_date 小于该记录开始日期的先前行。但这会导致大量往返数据库,这是我想避免的。
如果有一个解决方案,只需一个 SQL 查询即可获得我正在寻找的内容,那就太好了。
【问题讨论】:
-
您打算在桌子上放多少行。可以完成查询,但根据表的大小,可能会出现严重的性能问题。如果性能是您所需要的,那么您必须使用另一种方法来解决这个问题,而不仅仅是窗口查询。
-
每个 sku,这个表不会有那么多行。您可以说,每个 sku 将少于 1000 行。
-
我很难相信前三行的
start_dates 小于第三行的end_date,因为我很确定 2020 年 > 2019 年。这整件事充其量是可疑的。 -
@AdrianKlaver 我认为您没有完全阅读这个问题。坦率地说,我无法更好地解释它。当您假设有可能为未来日期设置价格时,这一切都是有道理的,这发生在酒店房间预订软件中。
标签: sql database postgresql window-functions