Puede hacer uso de un ARRAY escriba internamente. El tipo de argumento aún puede ser cualquier tipo numérico. Demostración con 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}'
);
La función de transición f_circavg()
se define STRICT
, por lo que ignora las filas con NULL
aporte. También establece un tercer elemento de matriz para identificar conjuntos con una o más filas de entrada; de lo contrario, CASE
la función final devuelve NULL
.
Tabla temporal para pruebas:
CREATE TEMP TABLE t (x float);
INSERT INTO t VALUES (2), (NULL), (3), (4), (5);
Lancé un NULL
valor para probar también el STRICT
magia. Llamar:
SELECT circavg(x) FROM t;
circavg
-------------------
-2.78318530717959
Verificación cruzada:
SELECT atan2(sum(sin(x)), sum(cos(x))) FROM t;
atan2
-------------------
-2.78318530717959
Devuelve lo mismo. Parece funcionar. En la prueba con una tabla más grande, la última expresión con funciones agregadas regulares fue 4 veces más rápida que el agregado personalizado.
Prueba para filas de entrada cero / solo entrada NULL:
SELECT circavg(x) FROM t WHERE false; -- no input rows
SELECT circavg(x) FROM t WHERE x IS NULL; -- only NULL input
Devuelve NULL
en ambos casos.