递归累积函数 - 重用结果行作为输入
Recursive cumulative function - reuse resulting rows as input
我尝试过数组、横向视图、递归视图、自定义函数、变量...我正在失去希望。
我正在寻找可以从下面的 table 生成“result_good”的函数。
"result_good" 是 "trx" 和其自身前几行的累加,乘以 "event"。
with t(id, trx, event, result_good) as
(values
(1, 20, 0.1, 2.000000),
(2,-10, 0.1, 1.200000),
(3, 20,-0.1,-3.320000),
(4,-10, 0.1, 1.988000),
(5, 20, 0.1, 4.186800),
(6,-10,-0.1,-3.605480),
(7, 20, 0.1, 5.244932)
)
-- non-recursive approximation of intended result
select *,
prev + event*sum(prev) over(
order by id range between unbounded preceding and 1 preceding
) as not_quite_my_tempo
from
(select t.*, event*sum(trx) over(order by id) as prev
from t
) t
order by id
x86_64-pc-linux-gnu64 位
上的 PostgreSQL 13.6
window 函数不递归运行,递归 CTE 不允许在递归项中聚合。
每个结果递归地影响下一行。此函数写入临时 table 并重用结果:
CREATE OR REPLACE FUNCTION f_special_running_sum()
RETURNS TABLE(id int, result text)
LANGUAGE plpgsql AS
$func$
DECLARE
t record;
BEGIN
DROP TABLE IF EXISTS pg_temp.result;
CREATE TEMP TABLE result (id int, trx int, result float8) ON COMMIT DROP;
FOR t IN
TABLE tbl ORDER BY id -- your actual table name here!
LOOP
INSERT INTO result(id, trx, result)
SELECT t.id, t.trx
, (COALESCE(sum(r.trx + r.result), 0) + t.trx) * t.event
FROM result r;
END LOOP;
-- format output
RETURN QUERY
SELECT r.id, to_char(r.result, 'FM9999990.000000')
FROM result r;
END
$func$;
db<>fiddle here
通话:
SELECT * FROM f_special_running_sum();
我将生成的数字格式化为文本以与您想要的结果完全匹配。您可能需要 numeric
或 double precision
。相应地进行调整。
大源 table 的性能会下降,因为每一行的成本都在不断增加。像 O(N²) 这样的东西。
小心 table-qualify 所有查询中的列名,因为相同的名称用于多种用途。
或者,递归函数 也可以。示例:
我尝试过数组、横向视图、递归视图、自定义函数、变量...我正在失去希望。
我正在寻找可以从下面的 table 生成“result_good”的函数。
"result_good" 是 "trx" 和其自身前几行的累加,乘以 "event"。
with t(id, trx, event, result_good) as
(values
(1, 20, 0.1, 2.000000),
(2,-10, 0.1, 1.200000),
(3, 20,-0.1,-3.320000),
(4,-10, 0.1, 1.988000),
(5, 20, 0.1, 4.186800),
(6,-10,-0.1,-3.605480),
(7, 20, 0.1, 5.244932)
)
-- non-recursive approximation of intended result
select *,
prev + event*sum(prev) over(
order by id range between unbounded preceding and 1 preceding
) as not_quite_my_tempo
from
(select t.*, event*sum(trx) over(order by id) as prev
from t
) t
order by id
x86_64-pc-linux-gnu64 位
上的 PostgreSQL 13.6window 函数不递归运行,递归 CTE 不允许在递归项中聚合。
每个结果递归地影响下一行。此函数写入临时 table 并重用结果:
CREATE OR REPLACE FUNCTION f_special_running_sum()
RETURNS TABLE(id int, result text)
LANGUAGE plpgsql AS
$func$
DECLARE
t record;
BEGIN
DROP TABLE IF EXISTS pg_temp.result;
CREATE TEMP TABLE result (id int, trx int, result float8) ON COMMIT DROP;
FOR t IN
TABLE tbl ORDER BY id -- your actual table name here!
LOOP
INSERT INTO result(id, trx, result)
SELECT t.id, t.trx
, (COALESCE(sum(r.trx + r.result), 0) + t.trx) * t.event
FROM result r;
END LOOP;
-- format output
RETURN QUERY
SELECT r.id, to_char(r.result, 'FM9999990.000000')
FROM result r;
END
$func$;
db<>fiddle here
通话:
SELECT * FROM f_special_running_sum();
我将生成的数字格式化为文本以与您想要的结果完全匹配。您可能需要 numeric
或 double precision
。相应地进行调整。
大源 table 的性能会下降,因为每一行的成本都在不断增加。像 O(N²) 这样的东西。
小心 table-qualify 所有查询中的列名,因为相同的名称用于多种用途。
或者,递归函数 也可以。示例: