用滞后填充空值,但不支持忽略空值

Fill nulls with lag, but ignore nulls isn't supported

我有一个 table 看起来像这样:

ID money_earned days_since_start
1 1000 1
1 2000 2
1 null 3
1 3000 4
1 2000 5
2 1000 1
2 null 2
2 100 3

我想要那些行,money_earned 中没有值(这意味着那天 money_earned 列是空的)- 将用最后一个已知值填充 money_earned,所以它看起来像这样:

ID money_earned days_since_start
1 1000 1
1 2000 2
1 2000 3
1 3000 4
1 2000 5
2 1000 1
2 1000 2
2 100 3

我试图查找类似的东西,但 postgresql 不支持在滞后 window 函数中忽略空值:(

谢谢!

The LOG() function would be suitable for this purpose, but in your case you need to get first not null previous element. What the LOG() function can't handle.

我建议创建您自己的函数,它将 return 前一个元素的第一个 non-null 值。

CREATE OR REPLACE FUNCTION log_not_null(row_num int, dafult text = '1001') RETURNS text LANGUAGE plpgsql AS $$
DECLARE
  result text; 
  index int;
BEGIN 
  if row_num > 0  then 
      index := row_num - 1;
   else
      return dafult;
   end if;
   result := (select money_earned from my_table  offset index limit 1);
   if result is null then 
     return log_not_null(index); 
   end if;  
   return result;
END
$$;


select id,  log_not_null((row_number() over ())::int) as money_earned, days_since_start from my_table;

注:

如果前一个值为 null,则递归调用该函数,直到到达顶部元素,如果最顶部的元素也为 null,则该函数将 returndafult 变量中的值。

演示在 DBfiddle

你可以这样做(警告,未经测试!):

UPDATE yourtable t1 
SET money_earned = t3.money_earned
FROM yourtable 
LEFT JOIN (SELECT 
                ID,
                MAX(days_since_start) m
           FROM yourtable 
           WHERE ID=t1.ID AND days_since_start<t1.ID) t2 ON t2.ID=i1.ID
INNER JOIN yourtable t3 ON t3.ID=t1.ID and t3.days_since_start = t2.days_since_start
WHERE t1.money_earned is null