您只需要构建一个介于min(startdate)和today之间的日期列表,其余的日期是直接的:
DECLARE @TestProject TABLE (Id INT IDENTITY(1, 1) PRIMARY KEY, Project NVARCHAR(50) NOT NULL, StartDate DATE NOT NULL, EndDate DATE NULL, Value INT NOT NULL);
INSERT INTO @TestProject VALUES
('AAA', '2018-01-01', NULL, 100),
('AAA', '2018-04-12', NULL, 50),
('BBB', '2018-01-01', '2018-03-01', 200),
('BBB', '2018-01-01', NULL, 20);
WITH cte AS (
SELECT DATEADD(DAY, 1, EOMONTH((SELECT MIN(StartDate) FROM @TestProject), -1)) AS ym
UNION ALL
SELECT DATEADD(MONTH, 1, ym)
FROM cte
WHERE DATEADD(MONTH, 1, ym) <= CURRENT_TIMESTAMP
)
SELECT ym, Project, SUM(Value)
FROM cte
LEFT JOIN @TestProject ON DATEADD(DAY, 1, EOMONTH(StartDate, -1)) <= ym AND (
EndDate IS NULL OR ym <= DATEADD(DAY, 1, EOMONTH(EndDate, -1))
)
GROUP BY ym, Project
在上面的例子中,
DATEADD(DAY, 1, EOMONTH(expr, -1))
函数用于生成指定日期的月初。