Du kan gøre brug af en ARRAY skriv internt. Argumenttype kan stadig være en hvilken som helst numerisk type. Demonstrerer med 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}'
);
Overgangsfunktionen f_circavg()
er defineret STRICT
, så den ignorerer rækker med NULL
input. Det sætter også et tredje array-element til at identificere sæt med en eller flere inputrækker - ellers CASE
den sidste funktion returnerer NULL
.
Midlertidig tabel til test:
CREATE TEMP TABLE t (x float);
INSERT INTO t VALUES (2), (NULL), (3), (4), (5);
Jeg smed en NULL
ind værdi for også at teste STRICT
magi. Ring til:
SELECT circavg(x) FROM t;
circavg
-------------------
-2.78318530717959
Krydstjek:
SELECT atan2(sum(sin(x)), sum(cos(x))) FROM t;
atan2
-------------------
-2.78318530717959
Returnerer det samme. Ser ud til at virke. I test med en større tabel var det sidste udtryk med regulære aggregerede funktioner 4x hurtigere end det tilpassede aggregerede.
Test for nul input rækker / kun NULL input:
SELECT circavg(x) FROM t WHERE false; -- no input rows
SELECT circavg(x) FROM t WHERE x IS NULL; -- only NULL input
Returnerer NULL
i begge tilfælde.