3

重要提示:我需要它与 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”)。

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

EDIT2:我目前正在寻找一种方法来进行第一次更新的操作(基于 4 个字段和日期的一天总计)但更快,我昨天已经接近它在光标内手动添加逻辑但光标太大且难以维护,那么对于这种情况,哪种跑步技术是最好的(更快)?您将如何在这里实施该技术?这不是一个简单的总计,当这些字段中的任何一个发生变化时都应该进行削减。字段EsSaldoAnterior变化只能为0或-1,当该字段为0时,更新只影响外部表,而当该字段为-1时,内部运行总计和。 EsSaldoAnterior表示类似于“其先前金额”的意思,这意味着运行总计不应从零开始,它们应首先开始对这些金额求和(如果存在),如果使用 ORDER BY,则为以下顺序:

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

2 回答 2

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

于 2013-12-02T15:22:17.230 回答
1

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

CodCustomer
ItemType
CodItem
EsCtaCorrienteMon
IsAvailable
OrderDate

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

将 OrderDate 列保留在索引的最后,以启用组内的快速范围搜索,从而提高日期比较效率。如果每组的日期很少,那么这种比较应该没有问题。

尝试使该索引聚集,以便子选择找到靠近外部临时行的行。

于 2013-12-12T09:29:12.050 回答