我需要获取两个日期时间之间的总分钟数,并要求时间落在另一个日期的时间不应计入开始日期的分钟数。例如数据如下
ID Start End taskId EmployeeId
1 2023-11-1 20:30:00 2023-11-1 23:30 2 1
2 2023-11-1 21:30:00 2023-11-1 23:30 2 2
3 2023-11-1 20:30:00 2023-11-2 01:30 2 3
4 2023-11-2 20:30:00 2023-11-2 23:30 2 1
5 2023-11-2 20:30:00 2023-11-2 23:30 2 2
6 2023-11-2 20:30:00 2023-11-3 00:30 2 3
Start 和 End Column 数据类型为 dateTime,其余 2 个为 int。
数据行3,从20:30到00:00的总分钟数,然后1个半小时落在2023-11-2,分钟应该计到2023-11-2的日期。可以这样做吗?
Select
Case
When
(Cast(EndDate as date) = Cast(EndDate as date) and Cast(StartDate as date) != Cast(EndDate as date)) then DateDiff(minute, Convert(datetime, Convert(varchar, Cast(EndDate as date)) + ' 00:00:00'), enddate)
When
DateDiff(Day, StartDate, EndDate) = 1 then DateDiff(Minute, StartDate, Convert(datetime, Convert(varchar, DateAdd(day, 1, Cast(StartDate as date))) + ' 00:00:00'))
else
DateDiff(MINUTE, StartDate, EndDate) End as [Total
Minutes], EmployeeId, taskId
From
tbl
Group By
EmployeeId, taskId
预期结果
Start End taskId EmpId minutes
2023-11-1 20:30:00 2023-11-1 23:30 2 1 180
2023-11-1 21:30:00 2023-11-1 23:30 2 2 120
2023-11-1 20:30:00 2023-11-2 01:30 2 3 210
2023-11-1 20:30:00 2023-11-2 01:30 2 3 90
2023-11-2 20:30:00 2023-11-2 23:30 2 1 180
2023-11-2 20:30:00 2023-11-2 23:30 2 2 180
2023-11-2 20:30:00 2023-11-3 00:30 2 3 210
2023-11-2 20:30:00 2023-11-3 00:30 2 3 30
您可以使用递归 CTE。会有点复杂。这是示例代码:
WITH RecursiveCTE AS (
SELECT
ID,
StartDateTime AS StartTime,
CASE
WHEN CAST(StartDateTime AS DATE) = CAST(EndDateTime AS DATE) THEN EndDateTime
ELSE DATEADD(DAY, 1, CAST(StartDateTime AS DATE))
END AS NewEndDate,
EndDateTime AS OriginalEndDateTime,
TaskID,
EmployeeID,
CASE
WHEN CAST(StartDateTime AS DATE) = CAST(EndDateTime AS DATE) THEN DATEDIFF(MINUTE, StartDateTime, EndDateTime)
ELSE DATEDIFF(MINUTE, StartDateTime, DATEADD(DAY, 1, CAST(StartDateTime AS DATE)))
END AS Minutes,
EndDateTime AS EndTime,
StartDateTime AS OriginalStartDate
FROM YourTableName
UNION ALL
SELECT
ID,
NewEndDate,
CASE
WHEN DATEADD(DAY, 1, CAST(OriginalEndDateTime AS DATE)) < OriginalEndDateTime THEN OriginalEndDateTime
ELSE DATEADD(DAY, 1, CAST(OriginalEndDateTime AS DATE))
END AS NewEndDate,
OriginalEndDateTime,
TaskID,
EmployeeID,
CASE
WHEN DATEADD(DAY, 1, CAST(OriginalEndDateTime AS DATE)) < OriginalEndDateTime THEN DATEDIFF(MINUTE, NewEndDate, OriginalEndDateTime)
ELSE DATEDIFF(MINUTE, NewEndDate, OriginalEndDateTime)
END AS Minutes,
EndTime,
OriginalStartDate
FROM RecursiveCTE
WHERE NewEndDate < OriginalEndDateTime
)
SELECT
OriginalStartDate AS [Start],
OriginalEndDateTime AS [End],
TaskID,
EmployeeID AS EmpId,
Minutes
FROM RecursiveCTE
ORDER BY OriginalStartDate,NewEndDate,EmployeeID;
这是示例输出:
您可以在此处查看dbfiddle