【问题标题】:Recursivly call on a lagged value in the same column, Or Have two interdependent columns递归调用同一列中的滞后值,或者有两个相互依赖的列
【发布时间】:2021-01-11 01:50:48
【问题描述】:

第一个查询没有运行,因为我在 LAG() 中有一个 SUM(),这是非法的,但我将其包含在内只是为了概念化这个想法。

SELECT
     GUID_Key
    ,AFE_Number
    ,UWI
    ,Date
    ,ACT_NET_AMOUNT
    ,Cum_Act
    ,FC_NET_AMOUNT
    ,Cum_FC
    ,ROWNUM
    ,IIF(Cum_FC > Cum_Act, FC_NET_AMOUNT, Cum_Act-ISNULL(LAG(SUM(Cum_Act)OVER(PARTITION BY Date))OVER (ORDER BY ROWNUM),0)) AS Result

FROM ready_set

或者

SELECT
     GUID_Key
    ,AFE_Number
    ,UWI
    ,Date
    ,ACT_NET_AMOUNT
    ,Cum_Act
    ,FC_NET_AMOUNT
    ,Cum_FC
    ,ROWNUM
    ,IIF(Cum_FC > Cum_Act, FC_NET_AMOUNT, IIF((LAG(CumRes) OVER( ORDER BY ROWNUM)) IS NULL, Cum_Act, Cum_Act - LAG(CumRes) OVER( ORDER BY ROWNUM))) AS Result
    ,IIF((LAG(CumRes) OVER( ORDER BY ROWNUM)) IS NULL ,/*Result*/IIF(Cum_FC > Cum_Act, FC_NET_AMOUNT, IIF((LAG(CumRes) OVER( ORDER BY ROWNUM)) IS NULL, Cum_Act, Cum_Act - LAG(CumRes) OVER( ORDER BY ROWNUM))), /*Result*/(IIF(Cum_FC > Cum_Act, FC_NET_AMOUNT, IIF((LAG(CumRes) OVER( ORDER BY ROWNUM)) IS NULL, Cum_Act, Cum_Act - LAG(CumRes) OVER( ORDER BY ROWNUM))) + Lag(CumRes) OVER ( ORDER BY ROWNUM))) AS CumRes
FROM ready_set

现在我应该提到在“ready_set”中有两个空列,result 和 CumRes,这就是第二个查询甚至运行的原因。

这是 Excel 电子表格中显示的确切想法。原则上它并不是非常复杂,但我猜它是在编程中! Excel Formula of the same idea

编辑:Excel results of the formula

同时,我试图在 CumRes 下保持结果的运行总计,并根据之前的累积计算结果。它们是相互依赖的,所以我不能简单地将结果相加来得到 CumRes 列。我并不完全了解 SQL 如何生成行,如果我试图滞后于正在制作而不是预先存在的列,我可能会采用完全错误的方法。你看到我的问题或思维错误了吗?

【问题讨论】:

  • 请提供示例数据、期望的结果以及您要实现的逻辑的清晰说明。
  • 要嵌套窗口聚合,您必须嵌套选择,即派生表或公用表表达式。
  • @GordonLinoff。抱歉,我无法向您提供该实际数据,因为它是机密的。您希望样本数据如何?以什么格式?底部的链接显示了公式,我添加了一个带有这些公式结果的附加图像。
  • @dnoeth 如果可以像您说的那样嵌套它们,您能否解释一下或指出我可以了解更多信息的方向?
  • 我假设您的结果可以通过简单的方式实现。您能否详细说明基于FC_NET_AMOUNTACT_NET_AMOUNT 的逻辑? (cum_actcum_fc 似乎是这些列的累积和加上 ROW_NUMBER)

标签: sql sql-server recursion


【解决方案1】:

如果你想要一个累计和:

select rs.*, sum(fc_net_amount) over (order by rownum)
from ready_set rs

【讨论】:

  • 谢谢,列的命名可能不是最好的,但 Cum_FC 是 FC_NET_AMOUNT 的累积总和。那不是我遇到的问题。
【解决方案2】:
create table tableX (rownum int not null,
    ACC_NET_ int not null, CumACT int not null,
    FC_NET_AMOUNT int not null, CumFC int not null);

insert into tableX (rownum, ACC_NET_, CumACT, FC_NET_AMOUNT, CumFc) values
    (1, 40, 40, 50, 50), (2, 164, 204, 2050, 2100), (3, 1513, 1717, 0, 2100),
    (4, 1000, 2717, 500, 2600), (5, 100, 2817, 0, 2600);    
go

with iterated as (
    select rownum, ACC_NET_, CumACT, FC_NET_AMOUNT, CumFc,
        iif(CumFc > CumACT, FC_NET_AMOUNT, CumACT - 0) as result,
        0 as CumRes
    from tableX
    where rownum = 1
    union all
    select x.rownum, x.ACC_NET_, x.CumACT, x.FC_NET_AMOUNT, x.CumFc,
        f.result,
        f.result + anchor.CumRes
    from iterated as anchor inner join tableX x
            on x.rownum = anchor.rownum + 1
        cross apply (
            select iif(x.CumFc > x.CumACT, x.FC_NET_AMOUNT, x.CumACT - anchor.CumRes)
        ) as f(result)
)
select * from iterated;

递归查询适用于您的公式。如果问题比您上面的数据所建议的要大,您可能需要阅读有关该主题的更多信息。此外,我确实必须添加一个 rownum 列才能按顺序对行进行排序。

编辑:我错误地播种了一个初始值并且已修复。

https://rextester.com/UXXY92525

【讨论】:

  • 谢谢!这本身就很好用,我试图让它在我的查询中工作,但运气不佳。我已将此标记为答案,因为我相信我还有其他问题需要解决,但这清楚地回答了我的问题。但是,我在查询中使用了其他 CTE,并且不断收到错误消息“类型在递归查询“迭代”的“CumRes”列中的锚点和递归部分之间不匹配。也许是因为 result_set 是一个 cte 而不是像你给我的例子那样的表?我不太确定。
  • 可能适用的递归查询存在限制。我怀疑错误意味着联合中的列没有正确排列,或者您至少需要进行转换以使它们兼容。
  • 我发现除了 CumRes 之外,我还必须将 Result 转换为浮点数,因为在将其添加到 CumRes 后,类型不再匹配!如果我有 15 个代表,我会支持你的回答,哈哈!我最终还使用了临时表,因为它更适合我的需求。谢谢一百万@shawnt00
  • 很高兴你明白了。如果您愿意,您当然可以稍后回来投票。
【解决方案3】:

这似乎符合您的公式:

with cte as 
 (
   select ACC_NET_AMOUNT, fc_NET_AMOUNT
     -- cumulative sums up to the previous rows
     , coalesce(sum(ACC_NET_AMOUNT) over (order by rownum rows between unbounded preceding and 1 preceding) ,0) as cumacc
     , coalesce(sum( FC_NET_AMOUNT) over (order by rownum rows between unbounded preceding and 1 preceding), 0) as cumfc
   from tableX
 )
select ACC_NET_AMOUNT, fc_NET_AMOUNT
  , ca.CumResult - case when cumfc > cumacc then cumfc else cumacc end as Result
  , ca.CumResult
from cte 
cross apply
 ( select
      case when cumfc+FC_NET_AMOUNT > cumacc + ACC_NET_AMOUNT 
           then cumfc+FC_NET_AMOUNT 
           else cumacc+ACC_NET_AMOUNT 
      end as CumResult) as ca

fiddle

【讨论】:

  • 谢谢,Dnoeth!这实际上在调整较少的情况下效果更好!谢谢!
猜你喜欢
  • 2018-12-26
  • 2013-12-13
  • 2019-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-26
  • 2017-08-16
相关资源
最近更新 更多