【问题标题】:Calculating information by using values from previous line使用上一行的值计算信息
【发布时间】:2013-01-23 16:59:19
【问题描述】:

我有每个帐户的当前余额,我需要减去交易的净额,以创建过去 24 个月的上个月的期末余额。下面是一个示例数据集;

create table txn_by_month (
memberid varchar(15)
,accountid varchar(15)
,effective_year varchar(4)
,effective_month varchar(2)
,balance money
,netamt money
,prev_mnthendbal money)

insert into txn_by_month values
(10001,111222333,2012,12,634.15,-500,1134.15)
,(10001,111222333,2012,11,NULL,-1436,NULL)
,(10001,111222333,2012,10,NULL,600,NULL)
,(10002,111333444,2012,12,1544.20,1650,-105.80)
,(10002,111333444,2012,11,NULL,1210,NULL)
,(10002,111333444,2012,10,NULL,-622,NULL)
,(10003,111456456,2012,01,125000,1200,123800)
,(10003,111456456,2011,12,NULL,1350,NULL)
,(10003,111456456,2011,11,NULL,-102,NULL)

如您所见,我已经有一个汇总了每个月所有交易的表格。我只需要在第一行计算上个月末余额并将其降至第二、第三行等。我一直在尝试使用 CTE,但对它们并不太熟悉,目前似乎被卡住了。这就是我所拥有的;

;
WITH CTEtest AS
(SELECT ROW_NUMBER() OVER (PARTITION BY memberid order by(accountid)) AS Sequence
,memberid
,accountid
,prev_mnthendbal
,netamt
FROM txn_by_month)

select c1.memberid
,c1.accountid
,c1.sequence
,c2.prev_mnthendbal as prev_mnthendbal
,c1.netamt, 
COALESCE(c2.prev_mnthendbal, 0) - COALESCE(c1.netamt, 0) AS cur_mnthendbal
FROM CTEtest AS c1
LEFT OUTER JOIN CTEtest AS c2 
ON c1.memberid = c2.memberid 
and c1.accountid = c2.accountid 
and c1.Sequence = c2.Sequence + 1

这仅适用于序列 = 2。我知道我的问题是我需要将我的 cur_mnthendbal 值降低到下一行,但我似乎无法理解如何。我需要另一个 CTE 吗?

任何帮助将不胜感激!

编辑:也许我需要更好地解释它......如果我有这个;

第 2 行的余额将是第 1 行的 prev_mnthendbal ($1,134.15)。然后第 2 行的 prev_mnthendbal 将是余额 - netamt ($1,134.15 - (-$1,436) = $2,570.15)。我一直在尝试使用 CTE,但我似乎无法弄清楚如何使用前一行中的 prev_mnthendbal 填充余额字段(因为在余额可用之前不会计算它)。也许我不能使用 CTE?我需要使用光标吗?

【问题讨论】:

    标签: sql sql-server sql-server-2008 cursor common-table-expression


    【解决方案1】:

    事实证明,我需要将运行总计与我开始使用的顺序 CTE 结合起来。

    ;
    with CTEtest AS
        (SELECT ROW_NUMBER() OVER (PARTITION BY memberid order by effective year, effective month desc) AS Sequence, *
        FROM txn_by_month)
    
    ,test
    as (select * , balance - netamt as running_sum from CTEtest where sequence = 1
    
    union all
    
    select t.*, t1.running_sum - t.netamt from CTEtest t inner join test t1
    
    on t.memberid = t1.memberid and t.sequence = t1.Sequence+1 where t.sequence > 1)
    
    select * from test
    order by memberid, Sequence
    

    希望这将在未来对其他人有所帮助。

    【讨论】:

    • t.sequence > 1 在这种情况下似乎完全没有必要。除此之外,是的,这几乎就是它经常做的事情。是的,您的回答确实可以帮助人们更快地找到此类问题的解决方案,即使是there are plenty of them already。 ;) 无论如何,你自己想出一个解决方案做得很好!
    【解决方案2】:

    请参阅 LEAD/LAG 分析函数。

    【讨论】:

    • 领先和滞后仅适用于 sql server 2012。我有 2008。我可以使用上面的 CTE 示例从上一行向下获取值。问题是它是NULL。我不知道如何将我的 NULL 替换为具有级联效应的上一行的值。
    • @Swizanson,对不起,我的假设是错误的,我不熟悉 SQL Server。然后您可能需要编写代码,例如将差异序列号分配给具有值的行和为空的行。 Lk 1 for value 和 0 for null 循环遍历所有记录...我仍然不知道如何在 SQL Server 中执行此操作,抱歉。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-11
    • 2018-03-26
    相关资源
    最近更新 更多