I have a table orders
in Postgres with columns offer_id
and date
. I need to write a query which fills in all null cases in column offer_id
, using the previous not-null value.
I tried to use the window function lag()
but it only manages with one single NULL, not several. How to fix that?
I tried this:
with orders as (
select 2 as offer_id, '2021-01-01'::date as date union all
select 3 as offer_id, '2021-01-02'::date as date union all
select null as offer_id, '2021-01-03'::date as date union all
select null as offer_id, '2021-01-04'::date as date union all
select null as offer_id, '2021-01-05'::date as date union all
select 4 as offer_id, '2021-01-07'::date as date union all
select 5 as offer_id, '2021-01-08'::date as date union all
select null as offer_id, '2021-01-09'::date as date union all
select 8 as offer_id, '2021-01-10'::date as date union all
select 9 as offer_id, '2021-01-11'::date as date union all
select null as offer_id, '2021-01-12'::date as date union all
select null as offer_id, '2021-01-13'::date as date union all
select 13 as offer_id, '2021-01-14'::date as date union all
select 13 as offer_id, '2021-01-15'::date as date union all
select null as offer_id, '2021-01-16'::date as date
)
SELECT *, CASE WHEN offer_id IS NULL
THEN LAG(offer_id) OVER (ORDER BY date) ELSE offer_id END AS updated_offer_id
FROM orders
2
Answers
Can be solved with a subquery forming groups:
fiddle
Since
count()
only counts not-null values, all rows with null fall into the one group with the preceding not-null value.In the outer
SELECT
, just pick the value of the first group member for all.Notably, this fills in the last preceding not-null value, not the greatest.
Leading null values stay null for lack of a leading template value. Related:
This code will work exactly same like the above one. But, It is more simpler and easy to understand for a beginner.