根据另一列和最终目标的增长率递归设置目标
Posted
技术标签:
【中文标题】根据另一列和最终目标的增长率递归设置目标【英文标题】:Recursively set targets based on growth rate in another column and end target 【发布时间】:2022-01-24 00:41:53 【问题描述】:day | growth_rate | target |
---|---|---|
1 | 1.2 | x |
2 | 1.3 | x |
3 | 1.4 | x = 909.09/1.4 |
4 | 1.2 | x = 1000/1.1 = 909.09 |
5 | 1.1 | 1000 |
因此,我尝试根据 SQL 中每一天的给定增长率来设置每天的目标。我们知道在一周/月结束时,目标是达到 1000。
在我们知道最终结果的情况下,编写递归(可能)函数来填充目标值 (x) 的方法是什么。
如果你能告诉我你是如何得到答案的,我也会非常感激。谢谢!
使用 postgress 仅供参考
【问题讨论】:
【参考方案1】:您可以使用对数恒等式,以便可以轻松地将生长因子相加 (Properties of Logarithms):
with data as (
select *,
max("target") over () / exp(sum(ln(growth_rate))
over (order by day desc)) as tgt
from T
)
select day, growth_rate,
coalesce(lead(tgt) over (order by day desc), target) as target
from data
order by day
不确定哪个是最干净的:
with data as (
select day,
max(target) over () as target,
lead(growth_rate) over (order by day) as growth_rate
from T
)
select day, growth_rate,
target / exp(sum(ln(growth_rate)) over (order by day desc)) as target
from data
order by day
https://dbfiddle.uk/?rdbms=postgres_10&fiddle=c9bbef6bb8192b5a8cff843ab6a009fc
【讨论】:
我只是编辑了它,我不认为我在寻找指数增长率,本质上我希望 1000/1.1 成为第 4 天的 x,然后在第 3 天执行相同的过程再次。像这样的东西?但它不起作用哈哈:coalesce(sum(lag(target, 1) / (growth_rate) over (order by days desc))), target) as tgt @ericsson95 这不是指数增长率。您只需要使用该函数来反转用于组合乘法因子的对数之和。 oh mybad 我一定是我的编辑器做错了,它工作得很好! 可能与上面的 1.4 有关系,应该是 1.2(在右栏中)。【参考方案2】:您的问题是window functions 的典型用例。但是不存在用于乘法或除法的内置窗口函数,因此您可以使用 sum()
聚合遵循 @shawnt00 的答案,也可以基于除法运算符创建自己的聚合:
CREATE OR REPLACE FUNCTION division (x anyelement, y anyelement, z anyelement)
RETURNS anyelement LANGUAGE sql AS $$ SELECT COALESCE(x,y)/z $$ ;
CREATE OR REPLACE AGGREGATE division_agg (x anyelement, z anyelement)
(sfunc = division, stype = anyelement) ;
然后您可以在查询中使用您的新聚合 division_agg
:
SELECT day, growth_rate
, COALESCE(division_agg(target, growth_rate) OVER (ORDER BY day DESC ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING), target)
FROM test
ORDER BY day
division_agg
窗口函数将由于ORDER BY day DESC
子句而对应于最高日的初始target
值依次除以与当前行关联的窗口的所有growth_rate
值,即所有行具有最高天,除了窗口为空的最高天的行,因此division_agg
返回NULL
,由于COALESCE()
函数,target
值被替换。
在dbfiddle 中查看完整演示。
【讨论】:
以上是关于根据另一列和最终目标的增长率递归设置目标的主要内容,如果未能解决你的问题,请参考以下文章