使用基于集合的操作快速计算sql server中的运行总计

时间:2011-08-11 01:45:46

标签: sql sql-server sql-server-2008

我有一些看起来像这样的数据:

+---+--------+-------------+---------------+--------------+
|   |   A    |      B      |       C       |      D       |
+---+--------+-------------+---------------+--------------+
| 1 | row_id | disposal_id | excess_weight | total_weight |
| 2 | 1      | 1           | 0             | 30           |
| 3 | 2      | 1           | 10            | 30           |
| 4 | 3      | 1           | 0             | 30           |
| 5 | 4      | 2           | 5             | 50           |
| 6 | 5      | 2           | 0             | 50           |
| 7 | 6      | 2           | 15            | 50           |
| 8 | 7      | 2           | 5             | 50           |
| 9 | 8      | 2           | 5             | 50           |
+---+--------+-------------+---------------+--------------+

我正在将它改造成这样:

+---+--------+-------------+---------------+--------------+
|   |   A    |      B      |       C       |      D       |
+---+--------+-------------+---------------+--------------+
| 1 | row_id | disposal_id | excess_weight | total_weight |
| 2 | 1      | 1           | 0             | 30           |
| 3 | 2      | 1           | 10            | 30           |
| 4 | 3      | 1           | 0             | 20           |
| 5 | 4      | 2           | 5             | 50           |
| 6 | 5      | 2           | 0             | 45           |
| 7 | 6      | 2           | 15            | 45           |
| 8 | 7      | 2           | 5             | 30           |
| 9 | 8      | 2           | 5             | 25           |
+---+--------+-------------+---------------+--------------+

基本上,我需要通过从表中先前行中减去属于同一dispos_id的excess_weights的总和来更新total_weight列。

我目前正在使用游标,因为它比我尝试过的其他解决方案更快(cte,三角形连接,交叉应用)。我的游标解决方案为每个新的dispos_id保留一个重置为零的运行总计,将其增加超重,并在需要时执行更新并在大约40秒内运行。我试过的其他解决方案花了3-5分钟,我想知道是否有一种相对高效的方法来使用基于集合的操作来做到这一点?

3 个答案:

答案 0 :(得分:2)

我花了很多时间来优化这些查询,结果有两个高性能选项:存储预先计算的运行总计,如Denormalizing to enforce business rules: Running Totals中所述,或者在客户端计算它们,这也很快捷

答案 1 :(得分:1)

您可能已尝试过的其他解决方案是执行类似here

的答案

除非您使用的是Oracle,它具有适当的累积总和,您最好使用游标。充其量,你将不得不重新加入表自己或使用另一种方法来进行O(n)操作。一般来说,针对这类问题的基于集合的解决方案是混乱的或非常混乱。

答案 2 :(得分:0)

'previous rows'意味着排序。所以没有 - 那里没有基于集合的操作。

Oracle的LEAD和LAG是为此而构建的,但是SQL Server会强制您进入三角形连接...我想你已经调查过了。