我对这个解决方案并不感到自豪,但我认为它对你有用。我的方法是创建一个天数表,然后查看车辆每天分配给哪个项目。最后,按月和年汇总得到结果。我必须以脚本的形式执行此操作,因为您可以在递归 CTE 的定义中使用聚合函数,但您可能会找到一种不需要递归 CTE 的方法。
我创建了一个表变量来导入您的数据,所以我可以写这个。请注意,我为跨越数月的测试作业添加了一个额外的作业。
DECLARE @Vehicles AS TABLE
(
[VehicleID] INT NOT NULL,
[Project] CHAR(2) NOT NULL,
[InspectionDate] DATE NOT NULL
);
INSERT INTO @Vehicles
(
[VehicleID],
[Project],
[InspectionDate]
)
VALUES
(1, 'P1', '2021-08-20'),
(1, 'P1', '2021-09-05'),
(1, 'P2', '2021-09-15'),
(1, 'P3', '2021-09-20'),
(1, 'P2', '2021-10-10'),
(1, 'P1', '2021-10-20'),
(1, 'P3', '2021-10-21'),
(1, 'P2', '2021-10-22'),
(1, 'P4', '2021-11-15'),
(1, 'P4', '2021-11-25'),
(1, 'P4', '2021-11-30'),
(1, 'P1', '2022-02-05');
DECLARE @StartDate AS DATE, @EndDate AS DATE;
SELECT @StartDate = MIN([InspectionDate]), @EndDate = MAX([InspectionDate])
FROM @Vehicles;
;WITH [seq]([n])
AS (SELECT 0 AS [n]
UNION ALL
SELECT [n] + 1
FROM [seq]
WHERE [n] < DATEDIFF(DAY, @StartDate, @EndDate)),
[days]
AS (SELECT DATEADD(DAY, [n], @StartDate) AS [d]
FROM [seq]),
[inspections]
AS (SELECT [VehicleID],
[Project],
[InspectionDate],
LEAD([InspectionDate], 1) OVER (PARTITION BY [VehicleID]
ORDER BY [InspectionDate]
) AS [NextInspectionDate]
FROM @Vehicles),
[assignmentsByDay]
AS (SELECT [d].[d], [i].[VehicleID], [i].[Project]
FROM [days] AS [d]
INNER JOIN [inspections] AS [i]
ON [d].[d] >= [i].[InspectionDate]
AND [d] < [i].[NextInspectionDate])
SELECT [assignmentsByDay].[VehicleID],
[assignmentsByDay].[Project],
MONTH([assignmentsByDay].[d]) AS [month],
YEAR([assignmentsByDay].[d]) AS [year],
COUNT(*) AS [daysAssigned]
FROM [assignmentsByDay]
GROUP BY [assignmentsByDay].[VehicleID],
[assignmentsByDay].[Project],
MONTH([assignmentsByDay].[d]),
YEAR([assignmentsByDay].[d])
ORDER BY [year], [month], [assignmentsByDay].[VehicleID], [assignmentsByDay].[Project]
OPTION(MAXRECURSION 0);
输出是:
| VehicleID |
Project |
month |
year |
daysAssigned |
| 1 |
P1 |
8 |
2021 |
12 |
| 1 |
P1 |
9 |
2021 |
14 |
| 1 |
P2 |
9 |
2021 |
5 |
| 1 |
P3 |
9 |
2021 |
11 |
| 1 |
P1 |
10 |
2021 |
1 |
| 1 |
P2 |
10 |
2021 |
20 |
| 1 |
P3 |
10 |
2021 |
10 |
| 1 |
P2 |
11 |
2021 |
14 |
| 1 |
P4 |
11 |
2021 |
16 |
| 1 |
P4 |
12 |
2021 |
31 |
| 1 |
P4 |
1 |
2022 |
31 |
| 1 |
P4 |
2 |
2022 |
4 |