尝试在PostgreSQL中创建聚合函数

尝试在PostgreSQL中创建聚合函数,postgresql,aggregate-functions,plpgsql,Postgresql,Aggregate Functions,Plpgsql,我正在尝试在PostgreSQL中创建新的聚合函数来代替sum()函数 我在手册中开始了我的旅程 因为我想创建一个函数,它接受一个双精度值数组,求和,然后进行一些额外的计算,我首先创建了最后一个函数: takes double precision as input and gives double precision as output DECLARE v double precision; BEGIN IF tax > 256 THEN

我正在尝试在PostgreSQL中创建新的聚合函数来代替
sum()
函数

我在手册中开始了我的旅程

因为我想创建一个函数,它接受一个双精度值数组,求和,然后进行一些额外的计算,我首先创建了最后一个函数:

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);
运行该命令时得到的结果是:

错误:函数数组_agg(双精度,双精度[])不存在 不存在

我有点被困在这里,因为手册列出了现有的功能。我做错了什么

此外,当我跑步时:

\da
                     List of aggregate functions
 Schema | Name | Result data type | Argument data types | Description 
--------+------+------------------+---------------------+-------------
(0 rows)
我的安装根本没有聚合功能?还是只列出用户定义的函数

基本上我想了解的是:

1) 我是否可以使用现有函数对数组值求和

2) 如何了解函数的输入和输出数据类型?文档声称
array\u agg()
接受任何类型的输入

3) 我自己的聚合函数有什么问题

编辑1 为了提供更多信息并更清楚地了解我正在努力实现的目标:

我对几个表进行了一个巨大的查询,查询结果如下:

SELECT sum(tax) ... from (SUBQUERY) as foo group by id
我想用我自己的聚合函数替换那个求和函数,这样我就不必在后端进行额外的计算——因为它们都可以在数据库级别上完成

编辑2 我接受了蚂蚁的回答。由于最终解决方案来自评论,我将其发布在此处以供参考:

CREATE AGGREGATE aggregate_ee_income_tax (float8)
(
 sfunc = float8pl
,stype = float8
,initcond = '0.0'
,finalfunc = eeincometax
);

数组agg是聚合函数而不是常规函数,因此它不能用作新聚合的状态转换函数。您要做的是创建一个聚合函数,它有一个与array_agg相同的状态转换函数和一个自定义final函数

不幸的是,array_agg的状态转换函数是根据内部数据类型定义的,因此不能重用。幸运的是,core中已有一个函数,它已经完成了您想要的功能

CREATE AGGREGATE aggregate_ee_income_tax (float8)(
    sfunc = array_append,
    stype = float8[],
    initcond = '{}',
    finalfunc = eeincometax);

还请注意,您的类型混淆了,您可能希望将一组浮点聚合到一个数组,而不是将一组数组聚合到一个浮点。

除了@Ants极好的建议:

1.)您的最终功能可以简化为:

CREATE FUNCTION eeincometax(float8)
  RETURNS float8 LANGUAGE SQL AS
$func$
SELECT (least($1, 256) * 21) / 79
$func$;
2)你好像在和钱打交道?在这种情况下,我强烈建议使用类型(首选)或用于此目的。浮点运算通常不够精确

3.)骨料的初始条件可以仅为
0

CREATE AGGREGATE aggregate_ee_income_tax(float8)
(
  sfunc     = float8pl
 ,stype     = float8
 ,initcond  = 0
 ,finalfunc = eeincometax
);

4.)在您的情况下,
(最少(总和(税),256)*21)/79
可能比您的自定义聚合快。PostgreSQL提供的聚合函数是用C编写的,并针对性能进行了优化。我会用它来代替。

太棒了。这让我更接近我想要的,但eeincometax finalfunc期望的是单个float8值,而不是数组。而array_append似乎只是输出数组。所以我仍然需要在finalfunction中进行实际的求和,或者有输出单个值的核心函数吗?因此,作为状态转换,需要一个函数,它接受两个浮点并返回它们的和。巧合的是,+操作符就是这么做的。为float8实现+运算符的函数称为float8pl。将sfunc更改为float8pl,将stype更改为float8,您应该是golden。不,我需要一个聚合函数,该函数接受一堆记录并对它们求和,然后将该和作为输入提供给finalfunc。就像我说的-我希望函数可以替换查询中的sum()函数。是的,这就是它要做的。作为转换函数的float8pl将值求和,并将最终值传递给func。我还忘了提到您需要将initcond更改为0.0.0。至少我没有犯错误地完成了一切。但价值产出似乎是错误的。我现在正在调试:)。从您的描述中,我不明白为什么不能使用
yourfinalfunc(sum(tax))
来转换最终结果?这将避免完全创建聚合函数。因为我提到的查询是通过编程方式组合在一起的,如果我要在另一个函数上添加一个函数,那么在组合查询的过程中,我必须做很多更改。添加大量的条件和诸如此类的东西——所有这些都会使以后理解代码变得更加困难。因此,只需更改求和函数就更容易了。感谢提供更多信息。不过,这只是一个问题——因为我的自定义聚合函数依赖于postgreSQL自己的float8pl函数,正如我从您的帖子中了解到的,它也是用C编写并优化的——我的函数实际增加了多少开销?@Zayatzz:最好只是测试一下。运行两个变体-可能几次以排除缓存效果。我对比较感兴趣。。。