SQL中当前记录日期字段当天或之前的累积每日总和

时间:2013-12-02 15:06:18

标签: sql-server optimization sql-server-2000 running-total rbar

重要:我需要将它与SQL Server 2000兼容。

我需要累积总和,但是根据当前日期字段,我现在使用的更新查询可以正常工作,但速度非常慢(丑陋的隐式RBAR三角形连接):

UPDATE #RPT 
SET DailySumAccum = 
      (SELECT SUM(COALESCE(CTACTE2.Amount,0))
       FROM #RPT_CTACTE CTACTE2
       WHERE CTACTE2.IsAvailable = #RPT_CTACTE.IsAvailable 
         AND CTACTE2.CodCustomer = #RPT_CTACTE.CodCustomer  
         AND CTACTE2.ItemType = #RPT_CTACTE.ItemType  
         AND CTACTE2.CodItem = #RPT_CTACTE.CodItem 
         AND EsCtaCorrienteMon = -1 
         AND DATEDIFF(day, CTACTE2.OrderDate, #RPT_CTACTE.OrderDate) >= 0) 
WHERE #RPT_CTACTE.EsSaldoAnterior = 0
  AND EsCtaCorrienteMon = -1

我也尝试使用游标方法来运行总计,但是我无法用它修复RBAR问题,看到日期比较仍然存在并且它仍然非常慢:

-- this is inside the cursor

IF (@EsCtaCorrienteMon = -1)
BEGIN
    SELECT @NetoDiarioAcum = SUM(COALESCE(Amount,0))
    FROM #RPT_CTACTE
    WHERE IsAvailable = @IsAvailable
          AND CodCustomer = @CodCustomer
          AND ItemType = @ItemType
          AND CodItem = @CodItem
          AND EsCtaCorrienteMon = -1
          AND DATEDIFF(day, OrderDate, @OrderDate) >= 0
END IF

所以,这个累积总和的问题是那里的日期比较,它使得查询超级慢(我在运行10分钟后停止了代码,评论此更新,光标只需要3秒钟运行),行数我测试的是28K,当记录计数增加时,它看起来时间呈指数上升,这就是为什么我认为问题是这里有一个RBAR(意思是“Row-By-Agonizing-Row”)。 / p>

编辑:经过一些测试后看起来日期并不是唯一的问题,有没有办法通过对游标内部的变量求和或类似的东西来制作这个运行总计?

EDIT2 :我目前正在寻找一种方法来制作第一次更新(根据4个字段和日期运行一天)但更快,我昨天已接近它在光标内部手动添加逻辑但是光标太大而难以保持,那么对于这种情况,运行总技术是最好的(更快)?你将如何在这里实现这种技术?这不是一个简单的运行总计,当任何这些领域发生变化时应该进行削减。字段EsSaldoAnterior更改只能是0或-1,更新仅在此字段为0时影响外部表,但即使此字段为-1,内部运行总计也是总和。 EsSaldoAnterior意味着“它的上一个数量”,这意味着运行总数不会从零开始,它们应该首先开始对这些数量进行求和(当它们存在时),这是使用ORDER BY时的顺序:

ORDER BY IsAvailable, CodCustomer, ItemType, CodItem, OrderDate, EsSaldoAnterior

2 个答案:

答案 0 :(得分:3)

尝试更改

AND DATEDIFF(day, CTACTE2.OrderDate, #RPT_CTACTE.OrderDate) >= 0) 

CTACTE2.OrderDate<DATEADD(dd, 0, DATEDIFF(dd, 0, #RPT_CTACTE.OrderDate)+1)

CTACTE2.OrderDate<DATEADD(dd, 1, DATEDIFF(dd, 0, #RPT_CTACTE.OrderDate))

在这种情况下,子查询应该使用CTACTE2.OrderDate上的索引

答案 1 :(得分:1)

要快速生成内部子选择,您需要在用于将内部查询与temptable相关联的列上添加索引:

CodCustomer
ItemType
CodItem
EsCtaCorrienteMon
IsAvailable
OrderDate

首先添加具有最多不同值(即具有高选择性)的列 - 首先没有IsAvailable,因为它只有两个不同的值。

将OrderDate列保留在索引的最后一列,以启用组内的快速范围搜索,以使日期比较更有效。如果每组的日期很少,那么这种比较应该不是问题。

尝试对此索引进行聚类,以便子选择查找其行靠近外部可测试行。