在SQL中生成步骤时间序列(PostgreSQL)

p5fdfcr1  于 2022-09-21  发布在  PostgreSQL
关注(0)|答案(2)|浏览(225)

我们将费率(例如:电价)对应的数据存储在一个SQL表中,例如:
Date|值

2022-08-25 01:00|12.3
2022-09-23 06:12|14.5
2022-10-18 05:34|9.8

两行之间的日期间隔不规则。在该表中,12.3是当前汇率,直到9月23日被新值替换,此时汇率变为14.5

从那里,我们希望生成每小时的时间序列,每个值对应于正确的速率,例如:
Date|值

2022-08-25 01:00|12.3
2022-08-25 02:00|12.3
2022-08-25 03:00|12.3
2022-08-25 04:00|12.3
2022-08-25 05:00|12.3
...|12.3
2022-09-23 06:12|14.5
2022-09-23 07:00|14.5
2022-09-23 08:00|14.5
...|14.5
2022-10-18 05:34|9.8
...|9.8

你将如何在PostgreSQL中生成这样的时间序列?

23c0lvtd

23c0lvtd1#

因此,您需要做两件事:生成每小时间隔的时间序列,然后检查在此期间value处于活动状态的每个间隔。

对于postgres,我还将创建一个timestamp range,它包含价格有效范围的开始和结束(不包括上限)。这可用于针对生成的时间序列的连接条件

with time_series ("date") as (
  select g.*
  from ( 
    select min("date") as start_date, max("date") as end_date
    from the_table
  ) x 
    cross join generate_series(x.start_date, x.end_date, interval '1 hour') as g
), ranges as (
  select tsrange("date", lead("date") over (order by "date"), '(]') as valid_during, 
         value
  from the_table
)
select ts."date",
       r.value 
from time_series ts
  join ranges r on r.valid_during @> ts."date"

如果您真的不需要“动态时间序列”,您可以只使用硬编码开始和结束的generate_series(),这将稍微简化这一点。

Online example

tuwxkamq

tuwxkamq2#

这是Postgres的解决方案。我认为这是您想要的,间隔以完整的小时结束,在生成结束后,下一个小时是来自原始表的准确的时间戳(参见表)。它是通过将生成的日期与原始日期截断为小时数进行比较来完成的。为了确保最后的日期出现在结果中,我在LAG上创建了COALESCE窗口函数,用最后的日期填充空值。希望它看起来不会太老土。
Hourly_Interval|取值

2022-08-25 01:00:00|12.3
2022-08-25 02:00:00|12.3
...|...
2022-09-23 06:00:00|12.3
2022-09-23 06:12:00|14.5
2022-09-23 07:00:00|14.5
...|...
2022-10-18 05:00:00|14.5
2022-10-18 05:34:00|9.8

结果为1303行

WITH cte AS (
    SELECT *,
    date_trunc('hour',generate_series(date,
        COALESCE((LAG(date,-1) OVER (ORDER BY date)),date),
        '1 hour')) hourly_interval
    FROM electricity
) 
SELECT
    CASE WHEN
        hourly_interval = date_trunc('hour',date)
    THEN
        date
    ELSE
        hourly_interval
    END AS hourly_interval,
    value
FROM cte

你可以自由地四处走动。

相关问题