Postgresql

使用 Postgres 繼承一長串缺失值

  • November 20, 2021

我有一張這樣的桌子:

create table foo (foo_label text, foo_price int, foo_date date);

insert into foo (
         values
         ('aaa', 100,  '2017-01-01'),
         ('aaa', NULL, '2017-02-01'),
         ('aaa', NULL, '2017-03-01'),
         ('aaa', NULL, '2017-04-01'),
         ('aaa', 140,  '2017-05-01'),
         ('aaa', NULL, '2017-06-01'),
         ('aaa', 180,  '2017-07-01')
       );

如您所見,該foo_price列上缺少一些值。

我需要的是缺失值以這種方式填充“以前的”可用值:

foo_label | fixed_foo_price | foo_date
-----------+-----------------+------------
aaa       | 100             | 2017-01-01
aaa       | 100             | 2017-02-01
aaa       | 100             | 2017-03-01
aaa       | 100             | 2017-04-01
aaa       | 140             | 2017-05-01
aaa       | 140             | 2017-06-01
aaa       | 180             | 2017-07-01

我的嘗試:

select 
   foo_label, 
   (case when foo_price is null then previous_foo_price else foo_price end) as fixed_foo_price,
   foo_date
from (
 select 
     foo_label, 
     lag(foo_price) OVER (PARTITION BY foo_label order by foo_date::date) as previous_foo_price, 
     foo_price,
     foo_date
     from foo
) T;

從這裡可以看出:

https://www.db-fiddle.com/#&togetherjs=s6giIonUxT

它並沒有完全填滿“100”系列。

知道如何獲得想要的結果嗎?

我將使用視窗函式組成組,count()然後為每個組取第一個值:

SELECT foo_label
    , first_value(foo_price) OVER (PARTITION BY foo_label, grp ORDER BY foo_date) AS fixed_foo_price
    , foo_date
FROM  (
  SELECT foo_label
       , count(foo_price) OVER (PARTITION BY foo_label ORDER BY foo_date) AS grp
       , foo_price
       , foo_date
  FROM   foo
  ) sub;

這是有效的,因為count()只計算非空值。因此,所有行NULL最終與具有實際值的最後一行位於同一組中。正是你需要的。

前導 NULL 值(實際上是“0”組)以NULL. COALESCE如果需要,請添加預設值。例如填寫0而不是NULL

    , COALESCE(first_value(foo_price) OVER (...), 0) AS fixed_foo_price

引用自:https://dba.stackexchange.com/questions/186218