SQL - sql 中的累计总和,基于连续日期
SQL - Cumulative sum in sql, base on continuous dates
假设我有一个 table 数据如下:
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 table 中没有 2015-10-03 数据,但累积 table 必须显示日期 2015-10-03
如果有人可以提供帮助,我们将不胜感激。
谢谢。
您可以使用 Tally Table:
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)
的所有日期。这是使用计数 table、从 E1(N)
到 Tally(N)
的 CTE
来完成的。
现在你有了所有的日期,对原来的table、TestTable
做一个LEFT JOIN
,得到对应的quantity
,赋值0
如果没有匹配的日期。
最后,要获得累计总和,可以使用SUM(quantity) OVER(ORDER BY deliver_date)
。
有关计数 table 的更多说明,请参阅我的
假设我有一个 table 数据如下:
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 table 中没有 2015-10-03 数据,但累积 table 必须显示日期 2015-10-03
如果有人可以提供帮助,我们将不胜感激。 谢谢。
您可以使用 Tally Table:
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)
的所有日期。这是使用计数 table、从 E1(N)
到 Tally(N)
的 CTE
来完成的。
现在你有了所有的日期,对原来的table、TestTable
做一个LEFT JOIN
,得到对应的quantity
,赋值0
如果没有匹配的日期。
最后,要获得累计总和,可以使用SUM(quantity) OVER(ORDER BY deliver_date)
。
有关计数 table 的更多说明,请参阅我的