Using window function to carry forward first non-null value in a partition
The following query achieves the desired result:
select *, first_value(somevalue) over w as carryforward_somevalue
from (
select *, sum(case when somevalue is null then 0 else 1 end) over (partition by person order by id ) as value_partition
from test1
) as q
window w as (partition by person, value_partition order by id);
Note the null case statement - if IGNORE_NULL was supported by postgres window functions this wouldnt be needed (as mentioned by @ypercubeᵀᴹ)
The problem is in the gaps-and-islands category of problems. It's a pity that Postgres has not yet implemented IGNORE NULL
in window functions like FIRST_VALUE()
, otherwise it would be trivial, with a simple change in your query.
There are probably many ways for this to be solved using window functions or recursive CTEs.
Not sure if it is the most efficient way but a recursive CTE does solve the problem:
with recursive
cf as
(
( select distinct on (person)
v.*, v.somevalue as carry_forward
from visits as v
order by person, ts
)
union all
select
v.*, coalesce(v.somevalue, cf.carry_forward)
from cf
join lateral
( select v.*
from visits as v
where v.person = cf.person
and v.ts > cf.ts
order by ts
limit 1
) as v
on true
)
select cf.*
from cf
order by ts ;