Можете да използвате МАСИВ тип вътрешно. Типът на аргумента все още може да бъде произволен числов тип. Демонстриране с float (=double precision ):
CREATE OR REPLACE FUNCTION f_circavg (float[], float)
RETURNS float[] LANGUAGE sql STRICT AS
'SELECT ARRAY[$1[1] + sin($2), $1[2] + cos($2), 1]';
CREATE OR REPLACE FUNCTION f_circavg_final (float[])
RETURNS float LANGUAGE sql AS
'SELECT CASE WHEN $1[3] > 0 THEN atan2($1[1], $1[2]) END';
CREATE AGGREGATE circavg (float) (
sfunc = f_circavg
, stype = float[]
, finalfunc = f_circavg_final
, initcond = '{0,0,0}'
);
Функцията за преход f_circavg() е дефинирано STRICT , така че игнорира редове с NULL вход. Той също така задава трети елемент от масив за идентифициране на набори с един или повече входни редове - в противен случай CASE крайната функция връща NULL .
Временна таблица за тестване:
CREATE TEMP TABLE t (x float);
INSERT INTO t VALUES (2), (NULL), (3), (4), (5);
Хвърлих NULL стойност, за да тествате и STRICT магия. Обаждане:
SELECT circavg(x) FROM t;
circavg
-------------------
-2.78318530717959
Кръстосана проверка:
SELECT atan2(sum(sin(x)), sum(cos(x))) FROM t;
atan2
-------------------
-2.78318530717959
Връща същото. Изглежда, че работи. При тест с по-голяма таблица последният израз с обикновени агрегатни функции беше 4 пъти по-бърз от персонализирания агрегат.
Тествайте за нулеви входни редове / само NULL вход:
SELECT circavg(x) FROM t WHERE false; -- no input rows
SELECT circavg(x) FROM t WHERE x IS NULL; -- only NULL input
Връща NULL и в двата случая.