SQL - sql中的累积和,基于连续日期

时间:2015-10-21 03:06:34

标签: sql-server cumulative-sum

假设我有一个包含以下数据的表:

SELECT *
FROM TestTable
ORDER BY deliver_date

deliver_date    quantity
2015-10-01  5.00
2015-10-02  3.00
2015-10-05  10.00
2015-10-07  8.00
2015-10-08  6.00

我知道如何进行累积,如下所示:

SELECT t1.deliver_date, SUM(t2.quantity) AS cumQTY 
FROM TestTable t1 
INNER JOIN TestTable t2 ON t2.deliver_date <= t1.deliver_date 
GROUP BY t1.deliver_date
ORDER BY t1.deliver_date

结果:

deliver_date    cumQTY
2015-10-01  5.00
2015-10-02  8.00
2015-10-05  18.00
2015-10-07  26.00
2015-10-08  32.00

但是,我有可能得到如下结果吗?

deliver_date    cumQTY
2015-10-01  5.00
2015-10-02  8.00
2015-10-03  8.00
2015-10-04  8.00
2015-10-05  18.00
2015-10-06  18.00
2015-10-07  26.00
2015-10-08  32.00

意思是,日期必须连续不断。 例如:我的TestTable表中没有2015-10-03数据,但累积表必须显示日期2015-10-03

感谢有人可以提供帮助。 谢谢。

1 个答案:

答案 0 :(得分:2)

您可以使用Tally Table

执行此操作

SQL Fiddle

DECLARE @startDate  DATE,
        @endDate    DATE

SELECT
    @startDate  = MIN(deliver_date),
    @endDate    = MAX(deliver_date)
FROM TestTable

;WITH E1(N) AS(
    SELECT 1 FROM(VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))t(N)
),
E2(N) AS(SELECT 1 FROM E1 a CROSS JOIN E1 b),
E4(N) AS(SELECT 1 FROM E2 a CROSS JOIN E2 b),
Tally(N) AS(
    SELECT TOP(DATEDIFF(DAY, @startDate, @endDate) + 1)
        ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
    FROM E4
),
CteAllDates AS(
    SELECT
        deliver_date = DATEADD(DAY, t.N-1, @startDate),
        quantity = ISNULL(tt.quantity, 0)
    FROM Tally t
    LEFT JOIN TestTable tt
        ON DATEADD(DAY, N-1, @startDate) = tt.deliver_date
)
SELECT
    deliver_date,
    cumQty = SUM(quantity) OVER(ORDER BY deliver_date)
FROM CteAllDates

首先,您要生成从MIN(deliver_date)MAX(deliver_date)的所有日期。这是使用计数表完成的,CTEE1(N)Tally(N)

现在您已拥有所有日期,请在原始表LEFT JOIN上执行TestTable,以获取相应的quantity,如果没有匹配则指定0日期。

最后,要获得累计金额,您可以使用SUM(quantity) OVER(ORDER BY deliver_date)

有关计数表的更多说明,请参阅我的answer here.