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

标签 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

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

  1. 标记 U - 销售
  2. 标记 I - 进货
  3. 标记 V - 盘点

当标志 U 和 I 出现时,金额代表变化 当出现V标志时,该金额代表盘点时的总金额

换言之,我想找到每个 unice Art.No 的最新 V 交易,然后添加或减去 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 事务之前拥有值,如下所示

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 事务。

最佳答案

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

关于SQL Server 根据不同标志计算累积和/条件运行总计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50599371/

相关文章:

sql - 在 SQL Server 2005 中跳过第一行?

sql - 使用 LIKE 语句查询任何单词,而不是整个单词

sql - 检查日期时间是否为当前日期

sql - 查找用于将财政季度结果与上一年进行比较的查询

sql - 从仅前两列不同的表中选择数据

java - 在 JPA QL 中,如何按项目类别选择所有国家/地区?

mysql - 如何在 MySQL 中获取两个日期中较新的一个?

mysql - 你能发现 SQL 注入(inject)吗?

sql - 表基数

sql - 我下载了 mac os 的 mssql 工具,但它说 "sqlcmd: command not found"