【问题标题】:PostgreSQL: RANGE BETWEEN INTERVAL '10 DAY' AND CURRENT ROWPostgreSQL:间隔“10 天”和当前行之间的范围
【发布时间】:2019-03-15 04:58:15
【问题描述】:

我有一张表,其中存储了每件商品的每日价格。如果价格尚未更新,则表示当天没有该商品的记录。

我需要编写一个查询来检索每件商品的最新价格,回溯窗口为当前行日期后 10 天,否则返回 NULL。我正在考虑使用RANGE BETWEEN INTERVAL 语句来实现这一目标。比如:

SELECT
    DATE(datetime),
    item_id,
    LAST(price) OVER(
        PARTITION BY item_id
        ORDER BY datetime DESC
        RANGE BETWEEN INTERVAL '10 DAYS' AND CURRENT ROW
    ) AS most_recent_price_within_last_10days
FROM ...
GROUP BY
    date,
    item_id,
    price

不幸的是,这个查询引发了一个错误:

LINE 20:  RANGE BETWEEN INTERVAL '10 DAY' PRECEDING AND CURRENT ROW
          ^

我看到一篇旧博客文章说在 Postgres 中无法进行这样的操作。这仍然准确吗?

【问题讨论】:

  • 您可以使用此 WHERE 子句获取最后 X 天的行:WHERE your_date > NOW() - INTERVAL '10 days'
  • 能否提供一些实际数据和预期输出?
  • 这个选项是在 Postgres 11 中引入的
  • 不幸的是,我仅限于 GCP 中的 Postgres 9.6。

标签: sql postgresql range window-functions


【解决方案1】:

您可以使用 ROW_NUMBER() 提取每个项目最近 10 天内的最新记录:

SELECT * 
FROM (
    SELECT
        DATE(datetime),
        item_id,
        price AS most_recent_price_within_last_10days,
        ROW_NUMBER() OVER(PARTITION BY item_id ORDER BY datetime DESC) rn
    FROM ...
    WHERE datetime > NOW() - INTERVAL '10 DAY'
) x WHERE rn = 1

在子查询中,WHERE 子句对日期范围进行过滤; ROW_NUMBER() 为具有相同 item_id 的记录组中的每个记录分配一个排名,最近的记录在前。然后,外部查询只过滤行号为 1 的记录。

【讨论】:

  • 感谢您的回答。我已经改写了我的问题,以便更清楚。基本上,我想计算过去几年中每件商品的最新价格(回溯期为 10 天)。
  • @Gianluca:嗯,现在我不确定你的真正意思,即使是编辑过的问题。您能否再次编辑您的问题以显示示例数据和预期输出?
【解决方案2】:

一种方法是使用LAG() 和一些比较:

(CASE WHEN LAG(datetime) OVER (PARTITION BY item_id ORDER BY datetime) > datetime - interval '10 days'
      THEN LAG(price) OVER (PARTITION BY item_id ORDER BY datetime)
 END) as most_recent_price_within_last_10days

也就是说,您要查找的价格在前一行。唯一的问题是该行的日期是否足够新。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多