[英]Sum of value by month where data contains start and end dates
我有一個簡單的表,包含一個在開始日期和結束日期之間有效的特定值的項目。 它看起來像這樣:
+----+---------+------------+------------+-------+
| Id | Project | StartDate | EndDate | Value |
+----+---------+------------+------------+-------+
| 1 | AAA | 2018-01-01 | NULL | 100 |
| 2 | AAA | 2018-04-12 | NULL | 50 |
| 3 | BBB | 2018-01-01 | 2018-03-01 | 20 |
| 4 | BBB | 2018-01-01 | NULL | 200 |
+----+---------+------------+------------+-------+
我想創建一個視圖,每月/項目呈現一條記錄,顯示該月的值列的總和。 例:
+----+-------+---------+-------+
| Id | Month | Project | Value |
+----+-------+---------+-------+
| 1 | JAN | AAA | 100 |
| 2 | FEB | AAA | 100 |
| 3 | MAR | AAA | 100 |
| 4 | APR | AAA | 150 |
| 5 | MAY | AAA | 150 |
| 6 | JUN | AAA | 150 |
| 7 | JAN | BBB | 220 |
| 8 | FEB | BBB | 220 |
| 9 | MAR | BBB | 220 |
| 10 | APR | BBB | 200 |
| 11 | MAY | BBB | 200 |
| 12 | JUN | BBB | 200 |
+----+-------+---------+-------+
這個月的日子並不重要。 例如,來自項目表的Id 2表明,截至2018-04-12,項目AAA的附加值為50。 這意味着四月及之后的總和應為150。
對於項目BBB,您會看到項目在2018-03-01結束。 這意味着BBB的總和應該在APRIL(而不是March!)的20下降,因為該項目在3月仍然有效。
我想渲染月份直到當前月份(查詢執行日期)。 所以在我的例子中,我在2018年6月的某個地方執行了這個查詢。
這必須在SQL Server 2012上運行。
以下是表的腳本和一些虛擬數據:
CREATE TABLE [TestProject] (
[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] ([Project], [StartDate], [EndDate], [Value])
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);
你只需要建立一個MIN(StartDate)和今天之間的日期列表,其余的是直接的:
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))
函數用於生成指定日期的月初。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.