【问题标题】:Pass extra parameter to PostgreSQL aggregate final function将额外参数传递给 PostgreSQL 聚合最终函数
【发布时间】:2018-07-04 05:45:58
【问题描述】:

是向 PostgreSQL 聚合的最终函数传递额外参数以创建状态值的特殊 TYPE 的唯一方法吗?

例如:

CREATE TYPE geomvaltext AS (
    geom public.geometry,
    val double precision,
    txt text
);

然后把这个类型作为状态变量,让第三个参数(文本)最终到达最终函数?

为什么聚合不能将额外的参数传递给最终函数本身?任何实施原因?

所以我们可以很容易地构造,例如,采用方法的聚合:

SELECT ST_MyAgg(accum_number, 'COMPUTE_METHOD') FROM blablabla

谢谢

【问题讨论】:

    标签: sql postgresql aggregate-functions


    【解决方案1】:

    您可以定义具有多个参数的聚合。

    我不知道这是否能解决你的问题,但你可以这样使用它:

    CREATE OR REPLACE FUNCTION myaggsfunc(integer, integer, text) RETURNS integer
       IMMUTABLE STRICT LANGUAGE sql AS
    $f$
       SELECT CASE $3
               WHEN '+' THEN $1 + $2
               WHEN '*' THEN $1 * $2
               ELSE NULL
            END
    $f$;
    
    CREATE AGGREGATE myagg(integer, text) (
       SFUNC = myaggsfunc(integer, integer, text),
       STYPE = integer
    );
    

    可以这样使用:

    CREATE TABLE mytab
       AS SELECT * FROM generate_series(1, 10) i;
    
    SELECT myagg(i, '+') FROM mytab;
    
     myagg 
    -------
        55
    (1 row)
    
    SELECT myagg(i, '*') FROM mytab;
    
      myagg  
    ---------
     3628800
    (1 row)
    

    【讨论】:

    • 重点是“如何将附加参数传递给最终函数?”。将它们传递给状态函数很容易。
    • 没有办法做到这一点,你必须创建自己的类型。我的回答受到了您的示例的启发。您要解决的问题是什么?也许有比最终函数的额外参数更简单的方法。
    • 为什么PostgreSQL不允许在最终函数中添加额外的参数?它有很多有用的情况......这个决定的一些基础?
    • 没有必要。正如我的回答所解释的,您可以使用现有功能来实现它。您可以更直接地处理最终函数的参数,方法是使用状态的复合类型并将所需的参数作为此状态的元素之一。
    【解决方案2】:

    我通过创建一个自定义聚合函数解决了类似的问题,该函数一次执行所有操作并将它们的状态存储在一个数组中。

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

    和:

    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;
    $$;
    

    然后创建另一个函数,根据第二个参数选择一个结果:

    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;
    $$;
    

    用法:

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

    这样做的明显缺点是执行所有功能而不仅仅是一个功能的开销。但是,在处理简单的操作(例如加法、乘法等)时,在大多数情况下应该是可以接受的。

    【讨论】:

      【解决方案3】:

      您将不得不重写最终函数本身,在这种情况下,您不妨编写一组新的聚合函数,每个可能的 COMPUTE_METHOD 一个。如果COMPUTE_METHOD 是数据值或由数据值暗示,则可以使用 CASE 语句来选择适当的聚合方法。或者,您可能希望创建一个包含 accum_numberCOMPUTE_METHOD 字段的自定义复合类型,并编写一个使用这种新数据类型的新聚合函数。

      【讨论】:

      • "COMPUTE_METHOD" 是一个文本参数,指定在最终函数中必须如何计算最终结果。问题是将此参数传递给最终函数。显然,除了构建一个包含此文本参数的新类型之外,这是不可能的,这过于复杂。
      猜你喜欢
      • 2021-02-27
      • 1970-01-01
      • 2016-06-08
      • 1970-01-01
      • 2017-04-09
      相关资源
      最近更新 更多