基于日期的滚动总和(缺少日期时)

时间:2020-09-30 23:15:39

标签: sql tsql datetime sum window-functions

您可能已经知道将聚合结果滚动到特定数量的先前行上。即:过去7天内我吃了多少热狗

SELECT HotDogCount, 
       DateKey, 
       SUM(HotDogCount) OVER (ORDER BY DateKey ROWS 6 PRECEDING) AS HotDogsLast7Days
FROM dbo.HotDogConsumption

结果:

+-------------+------------+------------------+
| HotDogCount |  DateKey   | HotDogsLast7Days |
+-------------+------------+------------------+
|           3 | 09/21/2020 |                3 |
|           2 | 9/22/2020  |                5 |
|           1 | 09/23/2020 |                6 |
|           1 | 09/24/2020 |                7 |
|           1 | 09/25/2020 |                8 |
|           4 | 09/26/2020 |               12 |
|           1 | 09/27/2020 |               13 |
|           3 | 09/28/2020 |               13 |
|           2 | 09/29/2020 |               13 |
|           1 | 09/30/2020 |               13 |
+-------------+------------+------------------+

现在,我的问题是日期之间有间隔。因此,基本上,有一天,我的肠子和循环系统都在向我尖叫:“你到底在做什么,你会杀了我们所有人!”因此,我决定休息一天,现在没有任何记录。现在,当我使用“ ROWS 6 PRECEDING”方法时,我现在可以返回8天而不是7天,因为错过了一天。

所以,问题是,你们中的任何人是否知道我可以如何使用OVER子句真正使用日期值(例如“ DATEADD(day,-7,DateKey)”之类)来确定应该有多少行?无论我是一天只吃热狗还是整天都吃了7天,总算得出了真正的7天滚动总和?

请注意,在我没有吃任何热狗的日子里,记录为0是不可行的。我知道我可以使用日期数组并对其进行左连接并执行

CASE WHEN Datekey IS NULL THEN 0 END

交易类型,但我想找出是否存在一种不同的方法,可以根据日期动态确定行前值。

2 个答案:

答案 0 :(得分:3)

从理论上讲,窗口函数是正确的方法。但是要回顾过去的7天(不是行),我们需要一个range框架规范-不幸的是,SQL Server不支持该框架规范。

我将推荐一个子查询或横向联接:

select hdc.*, hdc1.*
from dbo.HotDogConsumption hdc
cross apply (
    select coalesce(sum(HotDogCount), 0) HotDogsLast7Days 
    from dbo.HotDogConsumption hdc1
    where hdc1.datekey >= dateadd(day, -7, hdc.datekey)
      and hdc1.datekey < hdc.datekey
) hdc1

您可能希望将子查询的where子句中的条件调整为所需的精确框架。上面的代码是最近7天(不包括今天)的计算结果。相当于您当前尝试的内容将是:

    where hdc1.datekey >= dateadd(day, -6, hdc.datekey)
      and hdc1.datekey <= hdc.datekey

答案 1 :(得分:1)

我有点老,但这就是我要去的方式:

SELECT
        HDC1.HotDogCount
       ,HDC1.DateKey
       ,( SELECT SUM( HDC2.HotDogCount )
            FROM HotDogConsumption HDC2
           WHERE HDC2.DateKey BETWEEN DATEADD( DD, -7, HDC1.DateKey )
                                  AND HDC1.DateKey ) AS 'HotDogsLast7Days'
  FROM
        HotDogConsumption HDC1
;

年龄较小的人可能会使用OUTER APPLY之类的东西。