Прямые аргументы в пользовательских агрегатных функциях PostgreSQL
Я создаю пользовательскую статистическую функцию, которая нуждается в дополнительном параметре. Точнее, это кумулятивный минимум (он же окно), который принимает в качестве второго параметра интервал времени, определяющий окно. Поскольку функция агрегирования работает с моими пользовательскими типами данных, я привел фиктивный пример, который вычисляет среднее значение из n последних значений столбца. Я знаю, что могу решить эту фиктивную проблему в PostgreSQL, но цель этого примера - только подчеркнуть мою проблему.
CREATE FUNCTION lastNavg_transfn(state integer[], next integer, n integer)
RETURNS integer[] AS $$
BEGIN
RETURN array_append(state, next);
END;
$$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION lastNavg_finalfn(state integer[], n integer)
RETURNS float AS $$
DECLARE
card integer;
count float;
sum float;
BEGIN
count := 0;
sum := 0;
card := array_length(state, 1);
FOR i IN greatest(1,card-n+1)..card
LOOP
sum := sum + state[i];
count := count + 1;
END LOOP;
RETURN sum/count;
END;
$$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE;
CREATE AGGREGATE lastNavg(integer, integer) (
SFUNC = lastNavg_transfn,
STYPE = integer[],
INITCOND = '{}',
FINALFUNC = lastNavg_finalfn,
PARALLEL = SAFE
);
Я получаю следующую ошибку
ERROR: function lastnavg_finalfn(integer[]) does not exist
SQL state: 42883
Как сказать PostgreSQL, что моей конечной функции также нужен прямой параметр? Я работаю над PostgreSQL 10.1. Я знаю, что согласно документации прямые параметры разрешены только для агрегатов с упорядоченным набором, но мне также понадобится прямой параметр для "обычных" агрегатов.
1 ответ
Вы можете определить агрегат с двумя аргументами и указать дополнительный параметр в качестве постоянного второго аргумента.
SFUNC
просто хранит второй аргумент, например, как 0-й элемент STYPE
целочисленный массив
FINALFUNC
имеет только один аргумент и получает n
от 0-го элемента массива.
Если вам нужен второй аргумент, который не является целым числом, определите составной тип и используйте его как STYPE
,
Не красиво, но это должно сработать.