使用SQL Server表变量中的运行总计算列

时间:2016-11-04 15:57:58

标签: sql-server variables running-total

我继承了一个存储过程,该过程利用表变量来存储数据,然后使用运行总计算更新每一行。表变量中记录的顺序非常重要,因为我们希望将数量从最高到最低排序(即,当您向下移动时,运行总数将变得越来越大。)

我的问题是,在更新表变量的步骤中,运行总计似乎在计算,但不是表格变量中的数据先前按(按最高音量降序)排序

var text = <%-JSON.stringify({ content: story.Content })%>.content; 

结果是,具有最高音量的记录,我预期首先计算的运行总计(因此运行总数= [音量]),不知何故在列表中进一步向下。运行总计似乎随机计算

这是我期望得到的:

Good result

但这是代码实际生成的内容:

enter image description here

不确定是否有办法在表变量上设置UPDATE语句,使其按卷desc排序?从我到目前为止所读到的,它可能是一个表变量的排序行为的问题,但不知道如何纠正?有人可以帮忙吗?

2 个答案:

答案 0 :(得分:2)

查看SQL中提供的Window函数

例如

Declare @YourTable table (ID int,Volume int)
Insert Into @YourTable values
(100,1306489),
(125,898426),
(150,907404)

Select ID
      ,Volume
      ,RunningTotal = sum(Volume) over (Order by Volume Desc)
 From  @YourTable 
 Order By Volume Desc

返回

ID  Volume  RunningTotal
100 1306489 1306489
150 907404  2213893
125 898426  3112319

要明确,@ YourTable仅用于演示目的。不需要将实际数据插入表变量。

  

编辑支持2008年(好消息是2008年支持Row_Number())

 Select ID
        ,Volume
        ,RowNr=Row_Number() over (Order by Volume Desc)
  Into  #Temp
  From  @YourTable 


 Select A.ID
       ,A.Volume
       ,RunningTotal = sum(B.Volume)
  From  #Temp A 
  Join  #Temp B on (B.RowNr<=A.RowNr)
  Group By A.ID,A.Volume
  Order By A.Volume Desc

答案 1 :(得分:1)

GarethD提供了计算跑步总数及其表现的多种方式的权威链接。正确的一个是最简单和最快的, 300倍更快,然后古怪的更新。这是因为它可以利用覆盖排序列的任何索引,并且因为它更简单。

我在这里重复一遍,说明当数据库提供适当的窗口函数时,这是多么简单

SELECT
    [Date],
    TicketCount,
    SUM(TicketCount) OVER (ORDER BY [Date] RANGE UNBOUNDED PRECEDING)
FROM dbo.SpeedingTickets
ORDER BY [Date];

SUM行表示:如果按日期排序,则对所有(UNBOUNDED)之前的行(PRECEDING)所有票据进行计数

最终比古怪的更新快300倍。

VolumeTable的等效查询将是:

SELECT   
   ID, 
   Volume, 
   ABS(Volume) as SortValue,
   SUM(Volume) OVER (ORDER BY ABS(Volume) DESC RANGE UNBOUNDED PRECEDING)
FROM  
   VolumeTable
ORDER BY ABS(Volume) DESC

请注意,如果排序列(Volume)上有索引,并且未使用ABS,则速度会快得多。在列上应用任何函数意味着优化器不能使用覆盖它的任何索引,因为实际的排序值与存储在索引中的值不同。

如果表非常大并且性能受损,您可以创建计算列并在其上创建索引