最近我一直在练习和研究PL / pgSQL。我一直在创建自定义聚合函数。
下面的代码可以正常工作,但是我无法编写这种类型的聚合函数:
SELECT my_aggregate_function(column) from table;
这是“部分工作的自定义集合”的代码:
CREATE OR REPLACE FUNCTION searchMinValue (numeric[]) RETURNS numeric AS $$
DECLARE
i numeric;
minVal numeric;
BEGIN
minVal := $1[1];
IF ARRAY_LENGTH($1,1) > 0 THEN --Checking whether the array is empty or not
<<confrontoMinimo>>
FOREACH i IN ARRAY $1 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',$1;
--Raising exception if the parameter passed as argument points to null.
RAISE EXCEPTION 'Cannot find Max value. Parameter % is null', $1
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;
其中表为Customers
,列为salary
类型的numeric
。
答案 0 :(得分:0)
您从根本上做对了事,但是您的实现仍然存在一些问题:
如果表为空,则汇总将出错。相反,它应该返回NULL
。
如果您要汇总的第一个值是NULL
,则您的汇总将做错事情。如果
minVal := $1[1];
将minVal
设置为NULL
,然后所有将来的比较minVal >= i
将不是为TRUE
,最终结果将为{{1 }},这不是您想要的。
您将所有值收集到一个数组中,如果您聚合许多行,该值将变得非常大。首先,这使您面临阵列用尽内存的危险,然后聚合的性能将不尽如人意。
最好在NULL
中执行比较:从SFUNC
开始,使用INITCOND = NULL
并在您处理新值时执行汇总。 STYPE = numeric
的相关部分如下所示:
SFUNC
那样,您根本不需要IF $1 IS NULL OR $1 > $2
RETURN $2;
ELSE
RETURN $1;
END IF;
。