【问题标题】:Adjusting a column value by subtracting previous running total from current row value in SQL Server通过从 SQL Server 中的当前行值中减去以前的运行总计来调整列值
【发布时间】:2021-05-01 21:44:20
【问题描述】:

我已经解决了这个问题并寻找了类似的线程,但还没有找到任何解决方案。

我尝试了几种方法,我将解释并举例说明数据和需要实现的目标:

我有一张像这样的表:

代码:

drop table if exists #temp

create table #temp 
(
     col1 varchar(10), 
     col2 varchar(10),
     col3 varchar(10), 
     [date] date,
     dateindex int, 
     totals money, 
     adjustement money 
)

insert into #temp 
values ('customer1', 'customer1', 'customer1', '01-01-2020', 1, 0, 100),
       ('customer1', 'customer1', 'customer1', '01-02-2020', 1, 0, 200),
       ('customer1', 'customer1', 'customer1', '01-03-2020', 1, 50, 0),
       ('customer1', 'customer1', 'customer1', '01-03-2020', 2, 100, 0),
       ('customer2', 'customer2', 'customer2', '01-04-2020', 1, 0, 150),
       ('customer2', 'customer2', 'customer2', '01-05-2020', 2, 0, 300),
       ('customer2', 'customer2', 'customer2', '01-06-2020', 1, 50, 0),
       ('customer2', 'customer2', 'customer2', '01-06-2020', 2, 100, 0)

我们有两个数字列:totalsadjustments,其余的是客户和日期的唯一属性。

当调整不为 0 时,这很好,我们不需要更改这些数字。

当总计不为 0 时,即我想要进行计算并希望更新同一行中 Adjustments 列的结果(当总计为 0 时,调整始终 = 0)。

替换那些 0 调整的计算应该是:当前总值 - 所有以前的调整(运行总计)

这是我尝试过的:

select 
    *,
    case 
       when totals <> 0 
           then totals - sum(adjustement) over (partition by col1,col2,col3  
                                                order by [date] asc, dateindex asc 
                                                rows between unbounded preceding and 1 preceding) 
           else adjustement 
    end as 'Calculation'    
from
    #temp

第 3 行返回正确的结果:50 - 300 = -250

现在,当您在同一天(第 3 行和第 4 行)、同一日期但不同的索引(用于知道哪个交易先出现的索引)有总计时,窗口函数正在执行 row4 = 100 -(100+200+ 0) =-200 当它需要为 100 - (100+200-250+0) = 50 时。

不包括前面的-250,因为它不是实际数据。我需要在计算时找到更新表格的方法,以便在移动下一行之前可以在表格上更新-250。

这个计算是针对每个客户完成的,这就是我按客户列进行分区的原因。

我非常感谢任何关于这方面的提示或建议,以及什么是最好的方法

谢谢!

【问题讨论】:

  • 当您的公式为 the current total value - all previous adjustments 时,为什么第 1 行和第 2 行是正值?
  • 你的意思是把case when放在sum里面吗?
  • 这真的很奇怪。您在同一天可能有多少个值?
  • Squirrel ,因为 else 条件。它只是把已经存在的东西放在那里。
  • @GordonLinoff 同一天的总数不超过 3 个。并且它们总是被索引为 1,2,3 。

标签: sql sql-server tsql sql-server-2016 common-table-expression


【解决方案1】:

我不太确定第三个索引在某个日期会如何工作。但是对于第二个索引(如您的示例),您可以进行两次计算:

select t.* ,
       (case when totals <> 0 and dateindex = 2
             then totals - sum(calculation) over (partition by  col1, col2, col3
                                                  order by date, dateindex
                                                  rows between unbounded preceding and 1 preceding
                                                 )
             else calculation 
        end) as Calculation_2   
from (select t.*,
             (case when totals <> 0 and dateindex = 1
                   then totals - sum(adjustement) over (partition by col1,col2,col3  
                                                        order by [date] asc,dateindex asc rows between unbounded preceding and 1 preceding) 
                   when dateindex = 1 then adjustement 
              end) as Calculation   
      from temp t
     ) t;

我怀疑第三个计算只需要另一个级别的子查询。

Here 是一个 dbfiddle。

【讨论】:

  • 我对子查询做了一些更改:当 'dateindex = 1 then adjustement' 时删除并替换为 'ELSE adjustement'。它正在工作,我们有两列具有不同的结果。我上面的另一点是有什么方法可以在继续计算的同时更新这些值?因为最终这些值需要在同一张表上更新
  • @usefjuan 。 . .最后,您可以将其全部设为 CTE 并更新 CTE。这是 SQL Server 的一大优点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-08-10
  • 2015-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多