Bạn có thể sử dụng ARRAY gõ nội bộ. Kiểu đối số vẫn có thể là bất kỳ kiểu số nào. Minh họa bằng 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}'
);
Hàm chuyển đổi f_circavg()
được xác định STRICT
, vì vậy nó bỏ qua các hàng có NULL
đầu vào. Nó cũng đặt một phần tử mảng thứ ba để xác định các bộ có một hoặc nhiều hàng đầu vào - nếu không thì CASE
hàm cuối cùng trả về NULL
.
Bảng tạm thời để thử nghiệm:
CREATE TEMP TABLE t (x float);
INSERT INTO t VALUES (2), (NULL), (3), (4), (5);
Tôi đã ném vào một NULL
giá trị để kiểm tra STRICT
ma thuật. Gọi:
SELECT circavg(x) FROM t;
circavg
-------------------
-2.78318530717959
Kiểm tra chéo:
SELECT atan2(sum(sin(x)), sum(cos(x))) FROM t;
atan2
-------------------
-2.78318530717959
Trả về như cũ. Có vẻ hiệu quả. Trong thử nghiệm với một bảng lớn hơn, biểu thức cuối cùng với các hàm tổng hợp thông thường nhanh hơn gấp 4 lần so với tổng hợp tùy chỉnh.
Kiểm tra không có hàng đầu vào / chỉ đầu vào NULL:
SELECT circavg(x) FROM t WHERE false; -- no input rows
SELECT circavg(x) FROM t WHERE x IS NULL; -- only NULL input
Trả về NULL
trong cả hai trường hợp.