我正在尝试在PostgreSQL中创建新的聚合函数来代替sum()
函数
我在手册here中开始了我的旅程。
因为我想创建一个带有双精度值数组的函数,然后对它们求和,然后做一些我最初创建的最终函数的额外计算:
takes double precision as input and gives double precision as output
DECLARE
v double precision;
BEGIN
IF tax > 256 THEN
v := 256;
ELSE
v := tax;
END IF;
RETURN v*0.21/0.79;
END;
然后我想创建一个聚合函数,它接受一个双精度值数组,并为我之前的函数提供一个双精度值来处理。
CREATE AGGREGATE aggregate_ee_income_tax (float8[]) (
sfunc = array_agg
,stype = float8
,initcond = '{}'
,finalfunc = eeincometax);
运行该命令时得到的是:
错误:函数array_agg(双精度,双精度[]) 不存在
我有点卡在这里,因为手册将array_agg()列为现有功能。我做错了什么?
另外,当我跑:
\da
List of aggregate functions
Schema | Name | Result data type | Argument data types | Description
--------+------+------------------+---------------------+-------------
(0 rows)
我的安装根本没有聚合功能?或者只列出用户定义的函数?
基本上我正在努力理解:
1)我可以使用现有函数来总结我的数组值吗?
2)如何找出函数的输入和ouptut数据类型?文档声称array_agg()
可以接受任何输入。
3)我自己的聚合函数有什么问题?
提供更多信息,更清楚地了解我正在努力实现的目标:
我对几个表有一个大问题,如下所示:
SELECT sum(tax) ... from (SUBQUERY) as foo group by id
我想用我自己的聚合函数替换sum函数,所以我不必在后端进行额外的计算 - 因为它们都可以在数据库级别完成。
接受蚂蚁的回答。由于最终解决方案来自评论,因此我将其发布在此处以供参考:
CREATE AGGREGATE aggregate_ee_income_tax (float8)
(
sfunc = float8pl
,stype = float8
,initcond = '0.0'
,finalfunc = eeincometax
);
答案 0 :(得分:3)
数组agg是一个聚合函数而不是常规函数,因此它不能用作新聚合的状态转换函数。你想要做的是创建一个聚合函数,它具有一个与array_agg和一个自定义最终函数相同的状态转换函数。
不幸的是,array_agg的状态转换函数是根据内部数据类型定义的,因此无法重用。幸运的是,核心中存在已经完成您想要的功能。
CREATE AGGREGATE aggregate_ee_income_tax (float8)(
sfunc = array_append,
stype = float8[],
initcond = '{}',
finalfunc = eeincometax);
另请注意,您的类型已经混淆了,您可能希望将一组浮点数聚合到一个数组中,而不是将一组数组聚合到一个浮点数。
答案 1 :(得分:3)
除了@Ants的优秀建议:
1。)您的最终功能可以简化为:
CREATE FUNCTION eeincometax(float8)
RETURNS float8 LANGUAGE SQL AS
$func$
SELECT (least($1, 256) * 21) / 79
$func$;
2。)好像你在处理钱?在这种情况下,我强烈建议您使用numeric
(首选)或money
类型。浮点运算通常不够精确。
3。)聚合的初始条件可以只是0
:
CREATE AGGREGATE aggregate_ee_income_tax(float8)
(
sfunc = float8pl
,stype = float8
,initcond = 0
,finalfunc = eeincometax
);
4.。)在您的情况下,(least(sum(tax), 256) * 21) / 79
可能比您的自定义聚合更快。 PostgreSQL提供的聚合函数是用C语言编写的,并针对性能进行了优化。我会改用它。