获取 2 个日期时间之间的总分钟数

问题描述 投票:0回答:1

我需要获取两个日期时间之间的总分钟数,并要求时间落在另一个日期的时间不应计入开始日期的分钟数。例如数据如下

  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
sql sql-server sql-server-2014
1个回答
0
投票

您可以使用递归 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

© www.soinside.com 2019 - 2024. All rights reserved.