U kunt gebruik maken van een ARRAY intern typen. Het argumenttype kan nog steeds elk numeriek type zijn. Demonstreren met 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}'
);
De overgangsfunctie f_circavg()
is gedefinieerd STRICT
, dus het negeert rijen met NULL
invoer. Het stelt ook een derde array-element in om sets met een of meer invoerrijen te identificeren - anders de CASE
de laatste functie retourneert NULL
.
Tijdelijke tabel om te testen:
CREATE TEMP TABLE t (x float);
INSERT INTO t VALUES (2), (NULL), (3), (4), (5);
Ik gooide een NULL
. in waarde om ook de STRICT
. te testen magie. Bel:
SELECT circavg(x) FROM t;
circavg
-------------------
-2.78318530717959
Kruiscontrole:
SELECT atan2(sum(sin(x)), sum(cos(x))) FROM t;
atan2
-------------------
-2.78318530717959
Geeft hetzelfde terug. Lijkt te werken. In een test met een grotere tabel was de laatste uitdrukking met reguliere aggregatiefuncties 4x sneller dan de aangepaste aggregatie.
Test voor nul invoerrijen / alleen NULL-invoer:
SELECT circavg(x) FROM t WHERE false; -- no input rows
SELECT circavg(x) FROM t WHERE x IS NULL; -- only NULL input
Retourneert NULL
in beide gevallen.