【问题标题】:Postgres user-defined aggregate function does not correctly assign valuePostgres 用户定义的聚合函数没有正确赋值
【发布时间】:2020-06-16 09:09:08
【问题描述】:

我对使用 postgresql 相当陌生,并尝试编写我的第一个用户定义的聚合函数。 select 函数向聚合函数发送每行的过去 20 个值。聚合函数以长度为 4 {counter, 'null', down, up} 的数字数组的形式提供初始值。空值是在迭代期间将存储先前值的位置。 'down' 和 'up' 是计数器并初始化为零。

状态转换函数将当前值与前一个值进行比较。如果当前值更高,则将差值加到上。如果较低,则将差异添加到下。新数组被传递到下一次迭代,当前值现在是旧值(数组中的第二个值),并且应该传递向上和向下的计数器。

问题似乎出在 IF 语句的某个地方。如果我将“向下”或“向上”增加 1,则这些值似乎会传递给下一次迭代。如果我添加差异“+ diff”,则“down”和“up”的值为零并且似乎永远不会改变。

仅将值递增 1 的代码:

CREATE OR REPLACE FUNCTION RSI_STATE(rsi_mat NUMERIC[], close_val numeric)
    RETURNS NUMERIC[]
LANGUAGE plpgsql
AS $$
DECLARE
    downs INTEGER;
    ups INTEGER;
    counter INTEGER;
    cl NUMERIC;
    diff NUMERIC;
BEGIN
    downs := rsi_mat[3];
    ups := rsi_mat[4];
    diff := abs(rsi_mat[2] - close_val);
    RAISE NOTICE 'Beginning Variable seed: %,  close: %,  down: %,  up: %,  diff: %', 
 rsi_mat[2], close_val, downs, ups, diff;

    IF rsi_mat[2] > close_val then
        RAISE NOTICE 'IF LESS down: %,  up: %,  diff: %', downs, ups, diff;
        downs := rsi_mat[3] + 1;
    ELSEIF rsi_mat[2] < close_val then
        RAISE NOTICE 'IF GREATER down: %,  up: %,  diff: %', downs, ups, diff;
        ups := rsi_mat[4] + 1;
    END IF;
    cl := close_val;
    counter := rsi_mat[1] + 1;
    RAISE NOTICE 'End Variable down: %,  up: %,  diff: %', downs, ups, diff;
    RETURN ARRAY[counter,cl, downs, ups];
END;
$$;

CREATE OR REPLACE FUNCTION RSI_FINAL(rsi_mat numeric[])
RETURNS NUMERIC
LANGUAGE PLPGSQL
AS $$
DECLARE
     RS NUMERIC;
BEGIN
     IF rsi_mat[3] = 0 then
         RS = 1000000;
     ELSE
         RS = rsi_mat[4]/rsi_mat[3];
     END IF;
     return (100 - (100/(1 + RS))); 
END;
$$;

SELECT RSI((dailyhist.dhist::json->>'close')::numeric)
OVER(PARTITION BY dailyhist.cusip ORDER BY dailyhist.datetime ROWS BETWEEN 19 PRECEDING AND CURRENT ROW) AS RSI
FROM dailyhist
limit 15

CREATE AGGREGATE RSI(NUMERIC)(
     SFUNC = RSI_STATE,
     STYPE = NUMERIC[],
     FINALFUNC = RSI_FINAL,
     INITCOND = '{1,null,0,0}'
);

添加 1 时的结果似乎会在每次迭代中更新值:

NOTICE: Beginning Variable seed: <NULL>, close: 3.37517, down: 0, up: 0, diff: <NULL> 
NOTICE: End Variable down: 0, up: 0, diff: <NULL> 
NOTICE: Beginning Variable seed: 3.37517, close: 3.41684, down: 0, up: 0, diff: 0.04167 
NOTICE: IF GREATER down: 0, up: 0, diff: 0.04167 
NOTICE: End Variable down: 0, up: 1, diff: 0.04167 
NOTICE: Beginning Variable seed: 3.41684, close: 3.396, down: 0, up: 1, diff: 0.02084 
NOTICE: IF LESS down: 0, up: 1, diff: 0.02084 
NOTICE: End Variable down: 1, up: 1, diff: 0.02084 
NOTICE: Beginning Variable seed: 3.396, close: 3.41684, down: 1, up: 1, diff: 0.02084 
NOTICE: IF GREATER down: 1, up: 1, diff: 0.02084 
NOTICE: End Variable down: 1, up: 2, diff: 0.02084 
NOTICE: Beginning Variable seed: 3.41684, close: 3.45851, down: 1, up: 2, diff: 0.04167 
NOTICE: IF GREATER down: 1, up: 2, diff: 0.04167 
NOTICE: End Variable down: 1, up: 3, diff: 0.04167 
NOTICE: Beginning Variable seed: 3.45851, close: 3.41684, down: 1, up: 3, diff: 0.04167 
NOTICE: IF LESS down: 1, up: 3, diff: 0.04167 
NOTICE: End Variable down: 2, up: 3, diff: 0.04167 
NOTICE: Beginning Variable seed: 3.41684, close: 3.29183, down: 2, up: 3, diff: 0.12501 
NOTICE: IF LESS down: 2, up: 3, diff: 0.12501 
NOTICE: End Variable down: 3, up: 3, diff: 0.12501 
NOTICE: Beginning Variable seed: 3.29183, close: 3.29183, down: 3, up: 3, diff: 0.00000 
NOTICE: End Variable down: 3, up: 3, diff: 0.00000 
NOTICE: Beginning Variable seed: 3.29183, close: 3.54184, down: 3, up: 3, diff: 0.25001 
NOTICE: IF GREATER down: 3, up: 3, diff: 0.25001 
NOTICE: End Variable down: 3, up: 4, diff: 0.25001 
NOTICE: Beginning Variable seed: 3.54184, close: 3.83352, down: 3, up: 4, diff: 0.29168 
NOTICE: IF GREATER down: 3, up: 4, diff: 0.29168 
NOTICE: End Variable down: 3, up: 5, diff: 0.29168 
NOTICE: Beginning Variable seed: 3.83352, close: 3.89603, down: 3, up: 5, diff: 0.06251 
NOTICE: IF GREATER down: 3, up: 5, diff: 0.06251 
NOTICE: End Variable down: 3, up: 6, diff: 0.06251 
NOTICE: Beginning Variable seed: 3.89603, close: 3.83352, down: 3, up: 6, diff: 0.06251 
NOTICE: IF LESS down: 3, up: 6, diff: 0.06251 
NOTICE: End Variable down: 4, up: 6, diff: 0.06251 
NOTICE: Beginning Variable seed: 3.83352, close: 3.83352, down: 4, up: 6, diff: 0.00000 
NOTICE: End Variable down: 4, up: 6, diff: 0.00000 
NOTICE: Beginning Variable seed: 3.83352, close: 4.04187, down: 4, up: 6, diff: 0.20835 
NOTICE: IF GREATER down: 4, up: 6, diff: 0.20835 
NOTICE: End Variable down: 4, up: 7, diff: 0.20835 
NOTICE: Beginning Variable seed: 4.04187, close: 4.25021, down: 4, up: 7, diff: 0.20834 
NOTICE: IF GREATER down: 4, up: 7, diff: 0.20834 
NOTICE: End Variable down: 4, up: 8, diff: 0.20834

Successfully run. Total query runtime: 274 msec. 15 rows affected.

尝试添加差异时出现问题。 IF 语句已从 +1 更改为 + diff:

CREATE OR REPLACE FUNCTION RSI_STATE(rsi_mat NUMERIC[], close_val numeric)
    RETURNS NUMERIC[]
LANGUAGE plpgsql
AS $$
DECLARE
    downs INTEGER;
    ups INTEGER;
    counter INTEGER;
    cl NUMERIC;
    diff NUMERIC;
BEGIN
    downs := rsi_mat[3];
    ups := rsi_mat[4];
    diff := abs(rsi_mat[2] - close_val);
    RAISE NOTICE 'Beginning Variable seed: %,  close: %,  down: %,  up: %,  diff: %', rsi_mat[2], close_val, downs, ups, diff;

    IF rsi_mat[2] > close_val then
        RAISE NOTICE 'IF LESS down: %,  up: %,  diff: %', downs, ups, diff;
        downs := rsi_mat[3] + diff;
    ELSEIF rsi_mat[2] < close_val then
        RAISE NOTICE 'IF GREATER down: %,  up: %,  diff: %', downs, ups, diff;
        ups := rsi_mat[4] + diff;
    END IF;
    cl := close_val;
    counter := rsi_mat[1] + 1;
    RAISE NOTICE 'End Variable down: %,  up: %,  diff: %', downs, ups, diff;
    RETURN ARRAY[counter,cl, downs, ups];
END;
$$;

结果显示 up 和 down 的值没有变化:

NOTICE:  Beginning Variable seed: <NULL>,  close: 3.37517,  down: 0,  up: 0,  diff: <NULL>
NOTICE:  End Variable down: 0,  up: 0,  diff: <NULL>
NOTICE:  Beginning Variable seed: 3.37517,  close: 3.41684,  down: 0,  up: 0,  diff: 0.04167
NOTICE:  IF GREATER down: 0,  up: 0,  diff: 0.04167
NOTICE:  End Variable down: 0,  up: 0,  diff: 0.04167
NOTICE:  Beginning Variable seed: 3.41684,  close: 3.396,  down: 0,  up: 0,  diff: 0.02084
NOTICE:  IF LESS down: 0,  up: 0,  diff: 0.02084
NOTICE:  End Variable down: 0,  up: 0,  diff: 0.02084
NOTICE:  Beginning Variable seed: 3.396,  close: 3.41684,  down: 0,  up: 0,  diff: 0.02084
NOTICE:  IF GREATER down: 0,  up: 0,  diff: 0.02084
NOTICE:  End Variable down: 0,  up: 0,  diff: 0.02084
NOTICE:  Beginning Variable seed: 3.41684,  close: 3.45851,  down: 0,  up: 0,  diff: 0.04167
NOTICE:  IF GREATER down: 0,  up: 0,  diff: 0.04167
NOTICE:  End Variable down: 0,  up: 0,  diff: 0.04167
NOTICE:  Beginning Variable seed: 3.45851,  close: 3.41684,  down: 0,  up: 0,  diff: 0.04167
NOTICE:  IF LESS down: 0,  up: 0,  diff: 0.04167
NOTICE:  End Variable down: 0,  up: 0,  diff: 0.04167
NOTICE:  Beginning Variable seed: 3.41684,  close: 3.29183,  down: 0,  up: 0,  diff: 0.12501
NOTICE:  IF LESS down: 0,  up: 0,  diff: 0.12501
NOTICE:  End Variable down: 0,  up: 0,  diff: 0.12501
NOTICE:  Beginning Variable seed: 3.29183,  close: 3.29183,  down: 0,  up: 0,  diff: 0.00000
NOTICE:  End Variable down: 0,  up: 0,  diff: 0.00000
NOTICE:  Beginning Variable seed: 3.29183,  close: 3.54184,  down: 0,  up: 0,  diff: 0.25001
NOTICE:  IF GREATER down: 0,  up: 0,  diff: 0.25001
NOTICE:  End Variable down: 0,  up: 0,  diff: 0.25001
NOTICE:  Beginning Variable seed: 3.54184,  close: 3.83352,  down: 0,  up: 0,  diff: 0.29168
NOTICE:  IF GREATER down: 0,  up: 0,  diff: 0.29168
NOTICE:  End Variable down: 0,  up: 0,  diff: 0.29168
NOTICE:  Beginning Variable seed: 3.83352,  close: 3.89603,  down: 0,  up: 0,  diff: 0.06251
NOTICE:  IF GREATER down: 0,  up: 0,  diff: 0.06251
NOTICE:  End Variable down: 0,  up: 0,  diff: 0.06251
NOTICE:  Beginning Variable seed: 3.89603,  close: 3.83352,  down: 0,  up: 0,  diff: 0.06251
NOTICE:  IF LESS down: 0,  up: 0,  diff: 0.06251
NOTICE:  End Variable down: 0,  up: 0,  diff: 0.06251
NOTICE:  Beginning Variable seed: 3.83352,  close: 3.83352,  down: 0,  up: 0,  diff: 0.00000
NOTICE:  End Variable down: 0,  up: 0,  diff: 0.00000
NOTICE:  Beginning Variable seed: 3.83352,  close: 4.04187,  down: 0,  up: 0,  diff: 0.20835
NOTICE:  IF GREATER down: 0,  up: 0,  diff: 0.20835
NOTICE:  End Variable down: 0,  up: 0,  diff: 0.20835
NOTICE:  Beginning Variable seed: 4.04187,  close: 4.25021,  down: 0,  up: 0,  diff: 0.20834
NOTICE:  IF GREATER down: 0,  up: 0,  diff: 0.20834
NOTICE:  End Variable down: 0,  up: 0,  diff: 0.20834

Successfully run. Total query runtime: 226 msec.
15 rows affected.

我不确定问题是逻辑、语法还是愚蠢。

【问题讨论】:

    标签: postgresql aggregate aggregate-functions


    【解决方案1】:

    您的错误是将upsdowns 定义为integer。这样,差值在赋值时被舍入为整数。

    将变量声明为numeric,你的问题就解决了。

    【讨论】:

    • 是的,这是我的问题,如此简单,但只需要另一双眼睛。非常感谢。
    猜你喜欢
    • 2021-06-25
    • 1970-01-01
    • 2017-10-13
    • 2019-03-06
    • 1970-01-01
    • 2015-12-03
    • 2016-10-16
    • 2015-07-06
    • 1970-01-01
    相关资源
    最近更新 更多