根据条件

时间:2018-03-14 07:05:46

标签: sql sql-server sum window-functions running-total

根据账户和日期计算另一列中的值加/减或另一个表B(重置总计)的运行总计。

示例

表A - 第一个场景

ID     Account  Date         Operation         Qty              Running_Total 
1       A       01/01/2018       plus           10              10
2       A       01/02/2018       plus           20              30 
3       A       01/03/2018       minus           5              20
4       A       01/03/2018       minus           5              20
5       A       01/04/2018       plus           30              50
6       B       01/01/2018       plus           15              15
7       B       01/02/2018       Use Table B    90              40 -- resets 
8       B       01/03/2018       plus           10              50

表A - 第二个场景

ID     Account  Date         Operation         Qty              Running_Total 
1       A       01/01/2018       plus           10              10
2       A       01/02/2018       plus           20              30 
3       A       01/03/2018       minus           5              20
4       A       01/03/2018       minus           5              20
5       A       01/04/2018       plus           30              50
6       B       01/01/2018       plus           15              15
7       B       01/02/2018       Use Table B    90              40-- resets (currently 80 using below solution)
7       B       01/02/2018       Use Table B    90              40-- resets (currently 80 using below solution)
8       B       01/03/2018       plus           10              50
9       B       01/04/2018       plus           20              75-- new row
10      B       01/04/2018       plus           5               75-- new row

表B

ID     Account  Date         RunningQty             
7      B       01/02/2018       40

原始代码:

select ID, Date, Operation, Total, 
              case when Operation = 'Use Table B' then TableB.RunningTotalQty 
              else
              SUM( case when Operation = 'plus' then  Qty 
                   else case when Operation = 'minus' then -Qty end) 
              OVER (PARTITION BY Account ORDER BY Date)  end
            From TableA A left Join TableB B 
on A.ID = B.ID ...

解决方案应用:(@ UZI'代码)

select
ID, Account, Date, Operation, Qty
   , Running_Total = sum(isnull(RunningQty, Qty * iif(Operation = 'plus', 1, -1))) over (partition by grp order by ID)
from (
select 
    a.*, b.RunningQty, grp = sum(isnull(b.RunningQty, 0)) over (order by a.ID)
from 
    @tableA a
    left join @tableB b on a.ID = b.ID and a.Account = b.Account  and a.Date = b.Date
) t

1 个答案:

答案 0 :(得分:1)

两个运行总计可能会解决您的问题:

declare @tableA table (ID int, Account char(1), Date date, Operation varchar(100), Qty int)
insert into @tableA
values 
(1, 'A', '01/01/2018', 'plus', 10)
, (2, 'A', '01/02/2018', 'plus', 20)
, (3, 'A', '01/03/2018', 'minus', 5)
, (4, 'A', '01/03/2018', 'minus', 5)
, (5, 'A', '01/04/2018', 'plus', 30)
, (6, 'B', '01/01/2018', 'plus', 15)
, (7, 'B', '01/02/2018', 'Use Table B', 90)
, (8, 'B', '01/03/2018', 'plus', 10)

declare @tableB table (ID int, Account char(1), Date date, RunningQty int)
insert into @tableB values (7, 'B', '01/02/2018', 40)

select
    ID, Account, Date, Operation, Qty
    , Running_Total = sum(isnull(RunningQty, Qty * iif(Operation = 'plus', 1, -1))) over (partition by grp order by ID)
from (
    select 
        a.*, b.RunningQty, grp = sum(isnull(b.RunningQty, 0)) over (order by a.ID)
    from 
        @tableA a
        left join @tableB b on a.ID = b.ID and a.Account = b.Account  and a.Date = b.Date
) t

输出:

ID  Account Date    Operation   Qty Running_Total
-------------------------------------------------
1   A   2018-01-01  plus        10  10
2   A   2018-02-01  plus        20  30
3   A   2018-03-01  minus       5   25
4   A   2018-03-01  minus       5   20
5   A   2018-04-01  plus        30  50
6   B   2018-01-01  plus        15  65
7   B   2018-02-01  Use Table B 90  40
8   B   2018-03-01  plus        10  50

编辑: 你只需要改变第一次运行总计。 sum() over (order by...)默认情况下按范围求和,因此您需要将其更改为按行添加

select
    ID, Account, Date, Operation, Qty
    , Running_Total = sum(isnull(RunningQty, Qty * iif(Operation = 'plus', 1, -1))) over (partition by grp order by ID)
from (
    select 
        a.*, b.RunningQty, grp = sum(isnull(b.RunningQty, 0)) over (order by a.ID rows unbounded preceding)
    from 
        @tableA a
        left join @tableB b on a.ID = b.ID and a.Account = b.Account  and a.Date = b.Date
) t