计算多行之间的日期差异 SQL
Calculate Date difference between multiple rows SQL
我需要计算多行之间的日期差异。场景是我有一辆可以在整个月以及当车辆被分配到不同项目时进行检查的车辆。我想计算每月或上个月将车辆分配给项目的天数。我尝试了多种方法,但我无法靠近。我对堆栈溢出比较陌生。如果有任何遗漏,我们深表歉意。请让我知道是否可以这样做。谢谢。
如果有帮助,所有列都集中在一个 table 中。请让我知道有关如何实现此目的的查询
我正在使用 SQL 服务器 2017。
原始数据
预期输出
我想你正在寻找这个:
select vehicleId
, Project
, month(inspectiondate) month
, year(inspectiondate) year
, datediff(day , min(inspectiondate), case when max(inspectiondate) = min(inspectiondate) then eomonth(min(inspectiondate)) else max(inspectiondate) end) days
from Vehicles
group by vehicleId, Project , month(inspectiondate), year(inspectiondate)
此查询针对 month/year 项目中每个特定车辆的每个 month/year,您将获得最大和最小检查日期并计算差异。
db<>fiddle here
我对这个解决方案并不感到自豪,但我认为它适合你。我的方法是创建 table 天,然后查看车辆每天分配给哪个项目。最后按月和年汇总得到结果。我必须将此作为脚本执行,因为您可以在递归 CTE 的定义中使用聚合函数,但您可能会找到一种无需递归 CTE 即可执行此操作的方法。
我创建了一个 table 变量来导入您的数据,所以我可以写这个。请注意,我添加了一个额外的作业来测试跨月的作业。
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
我需要计算多行之间的日期差异。场景是我有一辆可以在整个月以及当车辆被分配到不同项目时进行检查的车辆。我想计算每月或上个月将车辆分配给项目的天数。我尝试了多种方法,但我无法靠近。我对堆栈溢出比较陌生。如果有任何遗漏,我们深表歉意。请让我知道是否可以这样做。谢谢。
如果有帮助,所有列都集中在一个 table 中。请让我知道有关如何实现此目的的查询
我正在使用 SQL 服务器 2017。
原始数据
预期输出
我想你正在寻找这个:
select vehicleId
, Project
, month(inspectiondate) month
, year(inspectiondate) year
, datediff(day , min(inspectiondate), case when max(inspectiondate) = min(inspectiondate) then eomonth(min(inspectiondate)) else max(inspectiondate) end) days
from Vehicles
group by vehicleId, Project , month(inspectiondate), year(inspectiondate)
此查询针对 month/year 项目中每个特定车辆的每个 month/year,您将获得最大和最小检查日期并计算差异。
db<>fiddle here
我对这个解决方案并不感到自豪,但我认为它适合你。我的方法是创建 table 天,然后查看车辆每天分配给哪个项目。最后按月和年汇总得到结果。我必须将此作为脚本执行,因为您可以在递归 CTE 的定义中使用聚合函数,但您可能会找到一种无需递归 CTE 即可执行此操作的方法。
我创建了一个 table 变量来导入您的数据,所以我可以写这个。请注意,我添加了一个额外的作业来测试跨月的作业。
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 |