试图在PostgreSQL中创建聚合函数

时间:2012-09-13 07:14:41

标签: postgresql aggregate-functions plpgsql

我正在尝试在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)我自己的聚合函数有什么问题?

编辑1

提供更多信息,更清楚地了解我正在努力实现的目标:

我对几个表有一个大问题,如下所示:

SELECT sum(tax) ... from (SUBQUERY) as foo group by id

我想用我自己的聚合函数替换sum函数,所以我不必在后端进行额外的计算 - 因为它们都可以在数据库级别完成。

编辑2

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

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

2 个答案:

答案 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语言编写的,并针对性能进行了优化。我会改用它。