编写自定义聚合函数

Writing a custom aggregate function

最近我一直在练习和学习PL/pgSQL。我坚持创建自定义聚合函数。

下面的代码工作得很好,但我无法编写这种类型的聚合函数:

SELECT my_aggregate_function(column) from table;

这是"partially working custom aggregate"的代码:

CREATE OR REPLACE FUNCTION searchMinValue (numeric[]) RETURNS numeric   AS $$
  DECLARE 
     i numeric;
     minVal numeric;
  BEGIN
    minVal := [1];
    IF ARRAY_LENGTH(,1) > 0 THEN --Checking whether the array is empty or not
  <<confrontoMinimo>>
   FOREACH i IN ARRAY  LOOP --Looping through the entire array, passed as parameter
       IF minVal >= i THEN
           minVal := i;
       END IF;
   END LOOP confrontoMinimo;
   ELSE
    RAISE NOTICE 'Invalid parameter % passed to the aggregate function',;
   --Raising exception if the parameter passed as argument points to null.
   RAISE EXCEPTION 'Cannot find Max value. Parameter % is null', 
   USING HINT = 'You cannot pass a null array! Check the passed parameter';
END IF;
RETURN minVal;
END;
$$ LANGUAGE plpgsql;

CREATE AGGREGATE searchMinValueArray (numeric)
(
sfunc = array_append,
stype = numeric[],
finalfunc = searchMinValue,
initCond = '{}'
); 

 with w(v) as (select 5 union all select 2 union all select 3)
 select min(v) "Normal Aggregate", searchMinValueArray(v) "My Customed Aggregate" from w;

正如我之前所说,我想以这种方式调用我的自定义聚合函数:

SELECT my_aggregate_function(column) from table;

其中 table 是 Customers 并且该列是 salary 类型 numeric

你基本上做对了,但你的实现仍然存在一些问题:

  1. 如果 table 为空,您的聚合将出错。相反,它应该 return NULL.

  2. 如果您聚合的第一个值是 NULL,您的聚合将做错事。如果

    minVal := [1];
    

    minVal设置为NULL,那么以后所有的比较minVal >= i都会不是TRUE,最后的结果将是 NULL,这不是您想要的。

  3. 您将所有值收集在一个数组中,如果您聚合许多行,该数组将变得非常大。首先,这会使您面临 运行 数组内存不足的危险,然后聚合的性能将达不到应有的水平。

    SFUNC 中执行比较要好得多:从 INITCOND = NULL 开始,使用 STYPE = numeric 并在处理新值时执行聚合。 SFUNC 的相关部分如下所示:

    IF  IS NULL OR  > 
        RETURN ;
    ELSE
        RETURN ;
    END IF;
    

    这样你就根本不需要 FINALFUNC