Как сохранить результат из функции postgres в переменную? - PullRequest
1 голос
/ 13 июня 2019

У меня есть функция Postgres, которая должна возвращать столбец.

CREATE FUNCTION  fillvals_v1 (source_column numeric , order_by_col numeric) RETURNS numeric AS $$
    DECLARE
      fv_value numeric;
    BEGIN
        BEGIN
              select
                  first_value(src_col) over (partition by partition_col) as corrected_col
                      from (
                          select source_column as src_col, order_by_col,
                              sum(case when source_column is not null then 1 end) over (order by order_by_col) as partition_col
                                  from table_name
              ) t into fv_value;
              return cast(fv_value as numeric);
        END;
    END;
$$ LANGUAGE plpgsql STABLE;

Таблица table_name имеет такие значения

seq | close
-------+-------
     1 |     3
     2 |     4
     3 |     5
     4 |
     5 |
     6 |     3
(6 rows)

Итак, когда я вызываю эту функцию, как это

select fillvals_v1(close, seq) from table_name;

это дает мне следующий результат

fillvals_v1
-------------
           3
           4
           5


           3
(6 rows)

что не правильно.

Фактический результат, который я хочу, это

   seq | close
-------+-------
     1 |     3
     2 |     4
     3 |     5
     4 |     5
     5 |     5
     6 |     3
(6 rows)

То есть я хочу, чтобы все промежутки были заполнены последними значениями (упорядоченными по seq), которые не равны NULL.

Может кто-нибудь сказать мне, что здесь происходит не так? Возможно, что-то отсутствует в моей функции, или способ сохранения результата функции в переменной может быть неправильным.

1 Ответ

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

То, что вы хотите, это опция IGNORE NULLS на LAG(). Увы, Postgres (пока?) Не поддерживает это.

Я бы порекомендовал:

select t.*, max(close) over (partition by grp)       
from (select t.*,
             count(close) over (order by seq) as grp
      from tablename t
     ) t;

Вы также можете использовать боковое соединение (или подзапрос):

select t.seq,
       coalesce(t.close, tprev.close) as close
from tablename t left join lateral
     (select tprev.*
      from t tprev
      where tprev.seq < t.seq and
            t.close is null and
            tprev.close is not null
      order by tprev.seq desc
     ) tprev;

Однако первый метод должен быть быстрее.

...