Выбор самого последнего значения столбца из таблицы Postgres - PullRequest
1 голос
/ 03 мая 2020

У меня есть некоторые данные в таблице Postgres, которая выглядит следующим образом:

Name | Date      | Balance
--------------------------
A    |2020-01-01 |    1
B    |2020-01-01 |    0
B    |2020-01-02 |    2
A    |2020-01-03 |    5

(обратите внимание, что A отсутствует значение для 2020-01-02 и B для 2020-01-03 )

Я хотел бы заполнить пропущенную дату ее самым последним значением для этого имени. Другими словами, я бы хотел

Name | Date      | Balance
--------------------------
A    |2020-01-01 |    1
B    |2020-01-01 |    0
A    |2020-01-02 |    1 <--- filled in with previous balance
B    |2020-01-02 |    2
A    |2020-01-03 |    5
B    |2020-01-03 |    2 <--- filled in with previous balance

Обратите внимание, что в действительности несколько дат могут отсутствовать подряд, и в этом случае всегда следует выбирать самую последнюю дату для этого имени.

1 Ответ

1 голос
/ 03 мая 2020

Я имею в виду generate_series() и функции окна:

select 
    n.name, 
    s.date, 
    coalesce(t.balance, lag(balance) over(partition by n.name order by s.date) balance
from (select generate_series(min(date), max(date), interval '1 day') date from mytable) s
cross join (select distinct name from mytable) n
left join mytable t on t.name = n.name and t.date = s.date
order by n.name, s.date

Если у вас может быть несколько пропущенных дат подряд, тогда нужно немного больше логик c - это в основном эмулирует lag() с опцией ignore nulls:

select
    name,
    date,
    coalesce(balance, first_value(balance) over(partition by name, grp)) balance
from (
    select 
        n.name, 
        s.date, 
        t.balance,
        sum( (t.balance is not null)::int ) over(partition by n.name order by s.date) grp
    from (select generate_series(min(date), max(date), interval '1 day') date from mytable) s
    cross join (select distinct name from mytable) n
    left join mytable t on t.name = n.name and t.date = s.date
) t
order by name, date
...