Custom aggregate function

霸气de小男生 提交于 2019-12-11 15:31:39

问题


I am trying to understand aggregate functions and I need help.

So for instance the following sample:

CREATE OR REPLACE FUNCTION array_median(timestamp[])
  RETURNS timestamp AS
$$
    SELECT CASE WHEN array_upper($1,1) = 0 THEN null ELSE asorted[ceiling(array_upper(asorted,1)/2.0)] END
    FROM (SELECT ARRAY(SELECT ($1)[n] FROM
generate_series(1, array_upper($1, 1)) AS n
    WHERE ($1)[n] IS NOT NULL
            ORDER BY ($1)[n]
) As asorted) As foo ;
$$
  LANGUAGE 'sql' IMMUTABLE;


CREATE AGGREGATE median(timestamp) (
  SFUNC=array_append,
  STYPE=timestamp[],
  FINALFUNC=array_median
)

I am not understanding the structure/logic that needs to go into the select statement in the aggregate function itself. Can someone explain what the flow/logic is?

I am writing an aggregate, a strange one, that the return is always the first string it ever sees.


回答1:


You're showing a median calculation, but want the first text value you see?

Below is how to do that. Assuming you want the first non-null value, that is. If not, you'll need to keep track of if you've got a value already or not.

The accumulator function is written as plpgsql and sql - the plpgsql one lets you use variable names and debug it too. It simply uses COALESCE against the previous accumulated value and the new value and returns the first non-null. So - as soon as you have a non-null in the accumulator everything else gets ignored.

You may also want to consider the "first_value" window function for this sort of thing if you're on a modern (8.4+) version of PostgreSQL.

http://www.postgresql.org/docs/9.1/static/functions-window.html

HTH

BEGIN;

CREATE FUNCTION remember_first(acc text, newval text) RETURNS text AS $$
BEGIN
    RAISE NOTICE '% vs % = %', acc, newval, COALESCE(acc, newval);
    RETURN COALESCE(acc, newval);
END;
$$ LANGUAGE plpgsql IMMUTABLE;

CREATE FUNCTION remember_first_sql(text,text) RETURNS text AS $$
    SELECT COALESCE($1, $2);
$$ LANGUAGE SQL IMMUTABLE;

-- No "initcond" means we start out with null
--      
CREATE AGGREGATE first(text) (
    sfunc = remember_first,
    stype = text
);

CREATE TEMP TABLE tt (t text);
INSERT INTO tt VALUES ('abc'),('def'),('ghi');

SELECT first(t) FROM tt;

ROLLBACK;


来源:https://stackoverflow.com/questions/8350437/custom-aggregate-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!