Pass extra parameter to PostgreSQL aggregate final function

前端 未结 3 502
甜味超标
甜味超标 2020-12-18 09:39

Is the only way to pass an extra parameter to the final function of a PostgreSQL aggregate to create a special TYPE for the state value?

e.g.:

CREATE         


        
3条回答
  •  遥遥无期
    2020-12-18 10:25

    I solved a similar issue by making a custom aggregate function that did all the operations at once and stored their states in an array.

    CREATE AGGREGATE myagg(integer)
    (
        INITCOND = '{ 0, 1 }',
        STYPE = integer[],
        SFUNC = myaggsfunc
    );
    

    and:

    CREATE OR REPLACE FUNCTION myaggsfunc(agg_state integer[], agg_next integer)
    RETURNS integer[] IMMUTABLE STRICT LANGUAGE 'plpgsql' AS $$
    BEGIN
        agg_state[1] := agg_state[1] + agg_next;
        agg_state[2] := agg_state[2] * agg_next;
        RETURN agg_state;
    END;
    $$;
    

    Then made another function that selected one of the results based on the second argument:

    CREATE OR REPLACE FUNCTION myagg_pick(agg_state integer[], agg_fn character varying)
    RETURNS integer IMMUTABLE STRICT LANGUAGE 'plpgsql' AS $$
    BEGIN
        CASE agg_fn
            WHEN '+' THEN RETURN agg_state[1];
            WHEN '*' THEN RETURN agg_state[2];
            ELSE RETURN 0;
        END CASE;
    END;
    $$;
    

    Usage:

    SELECT myagg_pick(myagg("accum_number"), 'COMPUTE_METHOD') FROM "mytable" GROUP BY ...
    

    Obvious downside of this is the overhead of performing all the functions instead of just one. However when dealing with simple operations such as adding, multiplying etc. it should be acceptable in most cases.

提交回复
热议问题