根据另一列和最终目标的增长率递归设置目标

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 中查看完整演示。

【讨论】:

以上是关于根据另一列和最终目标的增长率递归设置目标的主要内容,如果未能解决你的问题,请参考以下文章

Mysql:设置主键自动增长起始值

SQL:根据另一列和上面的读取行连接列中的数据

服务机器人最终目标是达到人机共存的社会

使用 R 根据另一列中的类别计算列和列表之间常见值的百分比

使用 Filter 或 If Else 根据 R 中另一列中的值过滤指标

如何测试字符串包含列表中的元素并通过 Pandas 将目标元素分配给另一列