sqlpostgresqlnullpostgresql-9.2window-functions

Retrieve last known value for each column of a row


Not sure about the correct words to ask this question, so I will break it down.

I have a table as follows:

date_time | a | b | c

Last 4 rows:

15/10/2013 11:45:00 | null   | 'timtim' | 'fred'
15/10/2013 13:00:00 | 'tune' | 'reco'   | null
16/10/2013 12:00:00 | 'abc'  | null     | null
16/10/2013 13:00:00 | null   | 'died'   | null

How would I get the last record but with the value ignoring the null and instead get the value from the previous record.

In my provided example the row returned would be

16/10/2013 13:00:00 | 'abc' | 'died' | 'fred'

As you can see if the value for a column is null then it goes to the last record which has a value for that column and uses that value.

This should be possible, I just cant figure it out. So far I have only come up with:

select 
    last_value(a) over w a
from test
WINDOW w AS (
    partition by a
    ORDER BY ts asc
    range between current row and unbounded following
    );

But this only caters for a single column ...


Solution

  • This should work but keep in mind it is an uggly solution

    select * from
    (select dt from
    (select rank() over (order by ctid desc) idx, dt
      from sometable ) cx
    where idx = 1) dtz,
    (
    select a from
    (select rank() over (order by ctid desc) idx, a
      from sometable where a is not null ) ax 
    where idx = 1) az,
    (
    select b from
    (select rank() over (order by ctid desc) idx, b
      from sometable where b is not null ) bx 
    where idx = 1) bz,
    (
    select c from
    (select rank() over (order by ctid desc) idx, c
      from sometable where c is not null ) cx
    where idx = 1) cz
    

    See it here at fiddle: http://sqlfiddle.com/#!15/d5940/40

    The result will be

    DT                                   A        B      C
    October, 16 2013 00:00:00+0000      abc     died    fred