PostgreSQL last_value игнорирует нули - PullRequest
0 голосов
/ 24 июня 2019

Я знаю, что это уже спрашивали, но почему не работает решение ниже Я хочу заполнить value последним ненулевым значением, упорядоченным по idx.

Что я вижу:

 idx | coalesce 
-----+----------
   1 |        2
   2 |        4
   3 |         
   4 |         
   5 |       10
(5 rows)

Что я хочу:

 idx | coalesce 
-----+----------
   1 |        2
   2 |        4
   3 |        4 
   4 |        4 
   5 |       10
(5 rows)

Код:

with base as (

    select 1    as idx
         , 2    as value

    union

    select 2    as idx
         , 4    as value

    union

    select 3    as idx
         , null as value

    union

    select 4    as idx
         , null as value

    union

    select 5    as idx
         , 10   as value
)

select idx
     , coalesce(value
              , last_value(value) over (order by case when value is null then -1
                                                 else idx
                                                 end))
from base
order by idx

Ответы [ 3 ]

1 голос
/ 24 июня 2019

То, что вы хотите, это lag(ignore nulls).Вот один из способов сделать то, что вы хотите, используя две оконные функции.Первый определяет группировку для значений NULL, а второй - значение:

select idx, value, coalesce(value, max(value) over (partition by grp))
from (select b.*, count(value) over (order by idx) as grp
      from base b
     ) b
order by idx;

Вы также можете сделать это без подзапросов, используя массивы.В общем, возьмем последний элемент, не считая NULL с:

select idx, value, 
       (array_remove(array_agg(value) over (order by idx), null))[count(value) over (order by idx)]
from base b
order by idx;

Здесь - это скрипта db <>.

1 голос
/ 24 июня 2019

Ну, последнее значение здесь не имеет смысла для меня, если вы не можете указать мне.Глядя на пример, вам нужно последнее не значение, которое вы можете получить следующим образом: я формирую группу с нулями и предыдущим ненулевым значением, чтобы я мог получить первое не значение.

with base as (
select 1    as idx , 2    as value   union
select 2    as idx, -14    as value    union
select 3    as idx , null as value   union
select 4    as idx , null as value   union
select 5    as idx , 1   as value
)
Select idx,value,
first_value(value) Over(partition by rn) as new_val
from(
select idx,value
    ,sum(case when value is not null then 1 end) over (order by idx) as rn
  from   base
) t

здесьэто код

http://sqlfiddle.com/#!15/fcda4/2

1 голос
/ 24 июня 2019

Чтобы понять, почему ваше решение не работает, просто посмотрите на вывод, если вы упорядочите по порядку в рамке вашего окна:

with base as (
    select 1    as idx
         , 2    as value
    union
    select 2    as idx
         , 4    as value
    union
    select 3    as idx
         , null as value
    union
    select 4    as idx
         , null as value
    union
    select 5    as idx
         , 10   as value
)
select idx, value from base
order by case when value is null then -1
                                                 else idx
                                                 end;
 idx | value
-----+-------
   3 |
   4 |
   1 |     2
   2 |     4
   5 |    10

Функция окна last_value () выберет последнее значение втекущий кадр.Без изменения каких-либо параметров по умолчанию, это будет текущая строка.

...