在postgresql中编写我自己的聚合函数

时间:2015-06-05 13:02:11

标签: sql postgresql aggregate-functions

我从来没有弄过自己的聚会,只有存储程序,我需要一些建议。 我想编写一个自定义聚合,它将返回整数行的最大值并将其更改为10.我该怎么做?我试过这个:

public class LyncClientProvider
{
    private Thread _thread;
    private volatile bool _running;
    private volatile bool _clientRequested;
    private volatile LyncClient _lyncClient;

    private void MakeClientLoop()
    {
        while (_running)
        {
            if (_clientRequested) MakeClient();
            Thread.Sleep(100);
        }
    }

    private void MakeClient()
    {
        try
        {
            _lyncClient = LyncClient.GetClient();
        }
        catch (Exception)
        {
            _lyncClient = null;
        }
        _clientRequested = false;
    }

    public void Start()
    {
        if (_running) return;
        _running = true;
        _thread = new Thread(MakeClientLoop);
        _thread.Start();
    }

    public void Stop()
    {
        if (!_running) return;
        _running = false;
        _thread.Join();
        _clientRequested = false;
    }

    public LyncClient GetLyncClient()
    {
        if (!_running) return null;
        _clientRequested = true;
        while (_clientRequested) Thread.Sleep(100);
        return _lyncClient;
    }
}

但它没有用。有人可以帮助我吗?

我收到了错误:

CREATE AGGREGATE incremented_max ( v ) (
    SFUNC = max,
    STYPE = integer,
    INITCOND = max + 10
)

老实说,我并不了解它应该如何运作。

2 个答案:

答案 0 :(得分:4)

理查德的回答没有提到这个问题。您要求max()+10不是sum()+10

以下示例说明如何使用自定义函数创建聚合:

create function greaterint (int, int)
returns int language sql
as $$
    select case when $1 < $2 then $2 else $1 end
$$;

create function intplus10 (int)
returns int language sql
as $$
    select $1+ 10;
$$;

create aggregate incremented_max (int) (
    sfunc = greaterint,
    finalfunc = intplus10,
    stype = integer,
    initcond = 0
);

select incremented_max(v), max(V)
from (
    select 3 as v
    union select 10
    union select 12
    union select 5) alias

Sfunc是state transition function。它在聚合中执行的次数与要聚合的行数一样多。它的第一个参数是internal-state,即到目前为止累积的值。在第一次调用中,该值等于initcond(如果未定义null,则为initcond。第二个参数是next-data-value,即下一行的值。在上面的例子中,函数计算最大非空正整数,并执行四次(对于四行):

call #      internal-state     next-data-value       result
1           0 (initcond)       3                     3 (because 3 > 0)
2           3                  10                    10 (10 > 3)
3           10                 12                    12 (12 > 10)
4           12                 5                     12 (12 > 5)

Finalfunc在聚合结束时执行一次。它有一个参数(到目前为止计算的值)并返回聚合的最终(修改)结果。在我们的示例中,它只是将聚合的结果加10。

documentation中阅读更多内容。

上面的例子只是一种练习。事实上,没有必要定义这样的聚合,因为select max (v + 10)给出了期望的结果。

答案 1 :(得分:1)

BEGIN;

CREATE AGGREGATE inc_sum(int) (
    sfunc = int4pl,
    stype = int,
    initcond = 10
);

CREATE TEMP TABLE tt (i int);
INSERT INTO tt VALUES (1),(2),(3),(4);

SELECT sum(i), inc_sum(i) FROM tt;

ROLLBACK;

 sum | inc_sum 
-----+---------
  10 |      20
(1 row)

在上面的int4pl中是“+”的基础函数(通过列出以int开头然后猜测的函数找到)。

initcond是初始条件,所以从哪里开始。对于正常的总和为0。