【发布时间】: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