SQL Server根据不同的标志计算累积和/条件运行总计

时间:2018-05-30 08:02:38

标签: sql sql-server tsql

我在SQL Server中有一个表,数据看起来像这个例子。

ID  Flag    Art.No  Amount
1   U   A1000   -100
2   U   B2000   -5
3   V   B2000   900
4   U   B2000   -10
5   I   B2000   50
6   U   B2000   -20
7   U   A1000   -50
8   I   A1000   1000
9   V   A1000   3600
10  U   A1000   -500
11  U   A1000   -100
12  U   A1000   -2000
13  I   A1000   2000
14  U   A1000   -1000
15  I   C3000   10000
16  U   C3000   -4000
17  U   B2000   -5
18  U   B2000   -5
19  I   B2000   40
20  V   B2000   200
21  U   A1000   -500
22  U   B2000   -50
23  U   C3000   -1000

我想根据交易计算累计值。我的问题是该表包含3种类型的事务。

  1. 旗帜U - 销售
  2. 旗帜I - 收货
  3. Flag V - Stocktaking
  4. 当标志U和I出现时,数量代表变化 当标志V出现时,金额代表盘点时的总金额

    在单词中我想为每个unice Art.No找到最新的V-transaction,然后添加或减去U和I事务以获得每行的累积量。 如果没有V事务通过整个数据集。

    我已经为每个Art.No

    制作了预期结果的例子

    A1000

    ID  Flag    Art.No  Amount  A1000 Example
    1   U   A1000   -100    
    7   U   A1000   -50 
    8   I   A1000   1000    
    9   V   A1000   3600    3600
    10  U   A1000   -500    3100
    11  U   A1000   -100    3000
    12  U   A1000   -2000   1000
    13  I   A1000   2000    3000
    14  U   A1000   -1000   2000
    21  U   A1000   -500    1500
    

    B2000

    ID  Flag    Art.No  Amount  B2000 Example
    2   U   B2000   -5  
    3   V   B2000   900 
    4   U   B2000   -10 
    5   I   B2000   50  
    6   U   B2000   -20 
    17  U   B2000   -5  
    18  U   B2000   -5  
    19  I   B2000   40  
    20  V   B2000   200 200
    22  U   B2000   -50 150
    

    C3000

    ID  Flag    Art.No  Amount  C3000 Example
    15  I   C3000   10000   10000
    16  U   C3000   -4000   6000
    23  U   C3000   -1000   5000
    

    编辑: 要在数据集中获得更多历史记录,最好在最新的V-transaction之前获得值,如此

    B2000

    ID  Flag    Art.No  Amount  B2000 Example
    2   U   B2000   -5  150
    3   V   B2000   900 140
    4   U   B2000   -10 140
    5   I   B2000   50  190
    6   U   B2000   -20 170
    17  U   B2000   -5  165
    18  U   B2000   -5  160
    19  I   B2000   40  200
    20  V   B2000   200 200
    22  U   B2000   -50 150
    

    考虑每个I和U事务,但忽略V事务。

1 个答案:

答案 0 :(得分:4)

with cte as
 (
   select *,
      -- find the latest 'V' ID per ArtNo
      max(case when Flag = 'V' then ID end) 
      over (partition by ArtNo) as Last_V_ID
   from myTable
 )
select *,
   -- cumulative sum, but ignore all rows before the latest 'V' ID
   -- includes rows when there's no 'V' ID for this ArtNo
   sum(case when ID < Last_V_ID then null else Amount end)
   over (partition by ArtNo
         order by ID
         rows unbounded preceding)
from cte
order by ArtNo, ID

请参阅Fiddle

编辑:

要在最后一次盘点之前包含数据并忽略所有先前的库存,您可以使用此方法:

with cte as
 (
   select *,
      -- find the latest 'V' ID per ArtNo
      max(case when Flag = 'V' then ID end) 
      over (partition by ArtNo) as Last_V_ID
   from [dbo].[Warehouse]
 )
select *,
   -- cumulative sum, but ignore all rows before the latest 'V' ID
   -- includes rows when there's no 'V' ID for this ArtNo
   sum(case when ID < Last_V_ID then null else Amount end)
   over (partition by ArtNo
         order by ID
         rows unbounded preceding)
   -- calculate in-stock based on last 'V' ID, discarding all previous 'V' rows
  ,sum(case when (ID < Last_V_ID and Flag <> 'V')  then -Amount 
            when ID = Last_V_ID then Amount 
       end)
   over (partition by ArtNo
         order by ID 
         rows between 1 following and unbounded following)
from cte
order by ArtNo, ID

两种计算都是相互排斥的,因此您可以使用COALESCE轻松组合它们。

请参阅Fiddle