【问题标题】:Calculate running totals for multiple dates计算多个日期的运行总计
【发布时间】:2017-03-25 20:35:25
【问题描述】:

请查看问题底部的测试数据。

我有如下数据..

salesorder  datee
1          2016-11-10
1          2016-11-10
2          2016-11-09
2          2016-11-09

现在我想像下面这样显示我的数据

datee       Summ
2016-11-09  4
2016-11-10  6

所以我使用了下面的查询,这给了我确切的结果

select distinct 
datee,
sum(salesorder) over (order by datee)
from
#test

但上述查询的问题是,它使用 Range 选项并使用磁盘假脱机(如果工作表有记录,则它是基于磁盘的假脱机),而不是内存假脱机..您可以使用下面的方法进行验证

set statistics io on
select distinct 
datee,
sum(salesorder) over (order by datee)
from
#test

表“工作台”。扫描计数 3,逻辑读取 21,物理读取 0,预读读取 0,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。 表 '#test_______________________________________________________________________________________________________________00000001A8B8'。扫描计数 1,逻辑读取 1,物理读取 0,预读读取 0,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。

获取 InMemory spool 的一种方法是使用 Rows 选项,如下所示

select 
datee,
sum(salesorder) over ( order by datee rows between  unbounded preceding and  current row )
from
#test

上面的查询使用了 InMemory spool,速度非常快,但是输出不是我想要的。下面是输出

datee       summ
2016-11-09  2
2016-11-09  4
2016-11-10  5
2016-11-10  6

与磁盘假脱机相比,InMemoryspool 速度非常快。此处记录了这一点:Microsoft SQL Server 2012 High-Performance T-SQL Using Window Functions (Developer Reference)

所以我的问题是:
我如何使用 InMemory Spool 并获得我想要的结果。我尝试了各种框架选项,但我没有得到想要的结果

测试数据:

create table #test
(
salesorder int,
datee date
)
go

insert into #test
select 1,getdate()-1
go 2


insert into #test
select 2,getdate()-2
go 2

注意:
如果我没有重复的日期,行选项将起作用,但我的数据设置就是这样,并且我有数千条记录,如示例

更新:
这是大型查询的一部分,所以我更喜欢窗口函数(没有 CTE 或派生表)以避免重写

【问题讨论】:

  • 您是否尝试过选择不同的日期交叉应用到销售订单的总和?
  • 我认为,即使我使用不同日期的交叉应用,我也不会得到累积和,而且这是大型查询的一部分,所以我更喜欢窗口函数以避免重写
  • 如果你把派生表放在CTE里,你会避免重写吗?
  • @JuanCarlosOropeza:使用 CTE 方法将其集成到主查询非常困难,我已经向您展示了问题的摘要,如果我采用 cte 的方法,我必须加入两次..I现在已经更新了问题。抱歉之前没有更新
  • @TheGameiswar 只是想知道您从查询中看到的实际性能如何,但使用磁盘假脱机。

标签: sql sql-server tsql sql-server-2012 window-functions


【解决方案1】:
select distinct T1.dattee,X.Summ from SalesTab T1
    CROSS APPLY (SELECT SUM(T2.SalesOrder) SUMM FROM SalesTab T2 WHERE T2.dattee<=T1.dattee) X
    ORDER BY T1.Dattee

【讨论】:

    【解决方案2】:

    用这个怎么样:

    SELECT  datee, 
            sum(salesorder) over 
                ( order by datee rows between  unbounded preceding and  current row )
    FROM (
          SELECT datee,
                 sum(salesorder) as salesorder
          from #test
          GROUP BY datee
         ) t
    

    这给出了以下内容:

    表“工作台”。扫描计数 0,逻辑读取 0,物理读取 0, 预读读取 0,lob 逻辑读取 0,lob 物理读取 0,lob 预读读数为 0。 表 '#test_______________________________________________________________________________________________________________0000000000A3'。扫描计数 1,逻辑读取 1,物理读取 0,预读读取 0, lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。

    编辑:

    如果您不想使用此技术,请尝试以下变体 你自己的查询用 Row_NUMBER() 包装,仍然使用 IN Memeory:

    SELECT datee, salesorder
    FROM (
          SELECT datee, salesorder, 
                 ROW_NUMBER() OVER (PARTITION BY datee ORDER BY salesorder DESC) AS RN
          FROM (
                  SELECT  datee,
                          sum(salesorder) over ( order by datee rows between  unbounded preceding and  current row ) As salesorder
                  FROM #test
              ) t1
      ) t2
    WHERE RN = 1
    

    【讨论】:

    • 我有这个解决方案,但是由于很多原因我不想这样访问。谢谢
    • @TheGameiswar 也许你可以详细说明为什么不,所以其他人没有给出类似的答案?
    猜你喜欢
    • 2015-02-09
    • 1970-01-01
    • 2017-10-04
    • 2023-01-10
    • 1970-01-01
    • 1970-01-01
    • 2017-01-08
    • 1970-01-01
    • 2014-09-16
    相关资源
    最近更新 更多