当当前行为 null 时使用最后一个值,对于 PostgreSQL 时间序列 table

Use last value when current row is null , for PostgreSQL timeseries table

我遇到一个问题,我找不到最佳解决方案。所以我的想法是在每个给定时间从商店列表中获取产品列表的价格,但是因为价格是在不同时间注册的,所以我在按时间分组时得到一些空值,还有一个数组 o 值。因此,它需要几个步骤才能获得我需要的东西。我想知道是否有人知道更好、更快的方法来实现这一目标。 Bellow 是我最初的 PostgreSQL table 当然这只是其中的一个片段来理解这个想法:

初始Table

期望的结果(中间 table 和最后一个)

下面是 PostgreSQL sql 代码,它给出了我想要的结果,但它似乎非常昂贵:

SELECT times,
    first_value(price_yami_egg)  OVER (PARTITION BY partition_price_yami_egg order by time) as price_yami_egg
    first_value(price_yami_salt)  OVER (PARTITION BY partition_price_yami_salt order by time) as price_yami_salt
    first_value(price_dobl_egg)  OVER (PARTITION BY partition_price_dobl_egg order by time) as price_dobl_egg
    first_value(price_dobl_salt)  OVER (PARTITION BY partition_price_dobl_salt order by time) as price_dobl_salt

    FROM(
    SELECT time,
        min(price_yami_egg) as price_yami_egg,
        sum(case when min(price_yami_egg) is not null then 1 end) over (order by times) as partition_price_yami_egg
        min(price_yami_salt) as price_yami_salt,
        sum(case when min(price_yami_salt) is not null then 1 end) over (order by times) as partition_price_yami_salt
        min(price_dobl_egg) as price_dobl_egg,
        sum(case when min(price_dobl_egg) is not null then 1 end) over (order by times) as partition_price_dobl_egg
        min(price_dobl_salt) as price_dobl_salt,
        sum(case when min(price_dobl_salt) is not null then 1 end) over (order by times) as partition_price_dobl_salt
        FROM ( 
            SELECT "time" AS times,
                CASE WHEN  shop_name::text = 'yami'::text AND product_name::text = 'egg'::text THEN price END AS price_yami_egg
                CASE WHEN  shop_name::text = 'yami'::text AND product_name::text = 'salt'::text THEN price END AS price_yami_salt
                CASE WHEN  shop_name::text = 'dobl'::text AND product_name::text = 'egg'::text THEN price END AS price_dobl_egg
                CASE WHEN  shop_name::text = 'dobl'::text AND product_name::text = 'salt'::text THEN price END AS price_dobl_salt

                FROM shop sh
                 ) S

          GROUP BY time
          ORDER BY time) SS

你只是想要聚合吗?

select time,
       min(price) filter (where shop_name = 'Yami' and product_name = 'EGG'),
       min(price) filter (where shop_name = 'Yami' and product_name = 'SALT'),
       min(price) filter (where shop_name = 'Dobl' and product_name = 'EGG'),
       min(price) filter (where shop_name = 'Dobl' and product_name = 'SALT')
from shop s
group by time;

如果。你关心的是结果中的 NULL 值,然后你可以填写它们。这有点棘手,但想法是:

with t as (
      select time,
             min(price) filter (where shop_name = 'Yami' and product_name = 'EGG') as yami_egg,
             min(price) filter (where shop_name = 'Yami' and product_name = 'SALT') as yami_salt,
             min(price) filter (where shop_name = 'Dobl' and product_name = 'EGG') as dobl_egg,
             min(price) filter (where shop_name = 'Dobl' and product_name = 'SALT') as dobl_salt
      from shop s
      group by time
     )
select s.*,
       max(yaml_egg) over (yaml_egg_grp) as imputed_yaml_egg,
       max(yaml_salt) over (yaml_egg_grp) as imputed_yaml_salt,
       max(dobl_egg) over (yaml_egg_grp) as imputed_dobl_egg,
       max(dobl_salt) over (yaml_egg_grp) as imputed_dobl_salt
from (select s.*,
             count(yaml_egg) over (order by time) as yaml_egg_grp,

             count(yaml_salt) over (order by time) as yaml_egg_grp,

             count(dobl_egg) over (order by time) as dobl_egg_grp,

             count(dobl_salt) over (order by time) as dobl_salt_grp
      from s
     ) s