我需要为滚动和计算设置一个下限。例如,与
PKID NumValue GroupID
----------------------------
1 -1 1
2 -2 1
3 5 1
4 -7 1
5 1 2
我想拥有:
PKID RollingSum GroupID
----------------------------- ## Explanation:
1 0 1 ## 0 - 1 < 0 => 0
2 0 1 ## 0 - 2 < 0 => 0
3 5 1 ## 0 + 5 > 0 => 5
4 0 1 ## 5 - 7 < 0 => 0
当添加负数将导致和为负时,将激活限制以将结果设置为零。后续的加法应该基于这个调整后的值,而不是原来的滚动和。
使用加法应该达到预期的结果。如果第四个数字从 -7 变为 -3,则第四个结果应该是 2 而不是 0
如果可以提供一个总和而不是几个滚动数字,那也是可以接受的。我可以使用存储过程来实现非负加法,但这太低级了。
现实生活中的问题是我们将下订单记录为正数,将取消记录为负数。由于连接问题,客户可能会多次单击该cancel
按钮,这将导致记录多个负值。在计算我们的收入时,“零”需要作为销售的边界。
这个业务应用程序绝对是愚蠢的,但我对此无能为力。对于这个问题,请仅考虑 DBA 可以使用的解决方案。
我预计GroupID
最多每行五十行。
这是我想出的递归 CTE 示例(似乎可行)。Is 使用 Row_Number() OVER 创建一个没有间隙的序列号。我不知道它对您的数据的执行情况如何,但可以尝试一下。
下面是一个类似于 Scott Hodgin 的答案的递归解决方案,但它应该能够更好地利用索引。这将根据您的数据的外观提高性能。我用 20000 个组模拟了 100 万行数据。每个都有 50 行与之关联:
我添加到表中的非聚集索引应该允许 CTE 的递归部分通过一次索引查找来获取下一行。这也意味着表中数据的顺序
PK
没有关系。这里的另一个技巧是用来ROW_NUMBER()
有效地获取下一行。这是必要的,因为TOP
不能在 CTE 的递归部分中使用。这是查询:以下是结果示例:
在我的机器上,处理一百万行的代码大约需要 10 秒。我们可以看到每次迭代只返回一行的索引搜索:
我也在这里上传了实际计划。