Tenho uma tabela assim:
create table foo (foo_label text, foo_price int, foo_date date);
insert into foo (
values
('aaa', 100, '2017-01-01'),
('aaa', NULL, '2017-02-01'),
('aaa', NULL, '2017-03-01'),
('aaa', NULL, '2017-04-01'),
('aaa', 140, '2017-05-01'),
('aaa', NULL, '2017-06-01'),
('aaa', 180, '2017-07-01')
);
Como você pode ver, alguns valores na foo_price
coluna estão faltando.
O que eu preciso é que os valores ausentes sejam preenchidos com o valor disponível "anterior" desta maneira:
foo_label | fixed_foo_price | foo_date
-----------+-----------------+------------
aaa | 100 | 2017-01-01
aaa | 100 | 2017-02-01
aaa | 100 | 2017-03-01
aaa | 100 | 2017-04-01
aaa | 140 | 2017-05-01
aaa | 140 | 2017-06-01
aaa | 180 | 2017-07-01
Minha tentativa:
select
foo_label,
(case when foo_price is null then previous_foo_price else foo_price end) as fixed_foo_price,
foo_date
from (
select
foo_label,
lag(foo_price) OVER (PARTITION BY foo_label order by foo_date::date) as previous_foo_price,
foo_price,
foo_date
from foo
) T;
Como você pode ver daqui:
https://www.db-fiddle.com/#&togetherjs=s6giIonUxT
Não preenche completamente a série '100'.
Alguma ideia de como posso obter o resultado desejado?
Eu formaria grupos com a função window
count()
e depois pegaria o primeiro valor para cada grupo:Isso funciona porque
count()
conta apenas valores não nulos. Portanto, todas as linhas comNULL
terminam no mesmo grupo que a última linha com um valor real. Exatamente o que você precisa.Os valores NULL iniciais (efetivamente o grupo "0") terminam com
NULL
. Adicione um padrão comCOALESCE
se desejar. Por exemplo, para preencher em0
vez deNULL
:Preencher dados ausentes na demonstração passo a passo do postgresql
Crie uma tabela chamada
my_money
com um índice, numérico com nulos e uma data e insira algumas linhas.Faça uma tabela temporária para construir nossa coluna preenchida chamada:
backfilled_cci_val
Até aí tudo bem, mas não podemos preencher o primeiro nulo, porque ele não tem anterior, então você terá que decidir um valor inicial padrão manualmente com uma atualização:
O passo final é substituir o backfilled_cci_val da nova tabela de volta para cci_val da tabela original:
Alternativamente, se você gosta de viver perigosamente e fazer backfill de uma só vez e no local:
Essa instrução de atualização faz o mesmo que todas as anteriores, exceto que ela é implantada na tabela existente.
O que produz o mesmo resultado final explicado acima.