SQL-获取2个datetime之间的分钟数,但仅限于工作日

SQL-获取2个datetime之间的分钟数,但仅限于工作日,sql,sql-server-2008,tsql,Sql,Sql Server 2008,Tsql,我需要得到两次约会之间的分钟数。问题是我只需要计算一周中的分钟数。我的周末时间不算在内。另外,我们将周末定义为从周五下午5点开始到周一上午8点结束。我相信我已经创建了一个函数来计算一周中的时间,但它不计算星期五17:00-23:59和星期一00:00-7:59之间的时间。此计算可能跨越多个星期,因此需要每周过滤掉此时间 预期结果的一些例子如下: 09/09/15 09:15-09/10/15 18:30=1995分钟 09/09/15 09:15-09/11/15 18:30=3345分钟(周

我需要得到两次约会之间的分钟数。问题是我只需要计算一周中的分钟数。我的周末时间不算在内。另外,我们将周末定义为从周五下午5点开始到周一上午8点结束。我相信我已经创建了一个函数来计算一周中的时间,但它不计算星期五17:00-23:59和星期一00:00-7:59之间的时间。此计算可能跨越多个星期,因此需要每周过滤掉此时间

预期结果的一些例子如下:

  • 09/09/15 09:15-09/10/15 18:30=1995分钟
  • 09/09/15 09:15-09/11/15 18:30=3345分钟(周五柜台只开放到下午5点)
  • 09/09/15 09:15-09/12/15 18:30=3345分钟
  • 09/09/15 09:15-09/13/15 18:30=3345分钟
  • 09/09/15 09:15-09/14/15 18:30=3975分钟(计数器从周一晚上8点开始)
  • 09/11/15 18:30-09/12/15 18:30=0分钟(因为柜台在周五下午5点后开始营业,直到周一上午8点才开始营业)
  • 09/12/15 18:30-09/14/15 18:30=630分钟
以下是迄今为止的功能:

IF OBJECT_ID(N'WorkDaysMinutes', N'FN') IS NOT NULL
DROP FUNCTION [dbo].[WorkDaysMinutes]
GO
CREATE FUNCTION [dbo].[WorkDaysMinutes] (@StartDate DATETIME, @EndDate DATETIME = NULL) RETURNS FLOAT
AS
BEGIN
    DECLARE @Swap DATETIME
    DECLARE @Weekend_Start_Time NVARCHAR(5)
    DECLARE @Weekend_End_Time NVARCHAR(5)

    SET @Weekend_Start_Time = '17:00'
    SET @Weekend_End_Time = '08:00'

    IF @StartDate IS NULL
        RETURN NULL

    IF @EndDate IS NULL
        SELECT @EndDate = @StartDate

    IF @StartDate > @EndDate
        SELECT @Swap      = @EndDate,
               @EndDate   = @StartDate,
               @StartDate = @Swap

    RETURN (
        SELECT
    --Start with total number of minutes including weekends
        DATEDIFF(MI,@StartDate, @EndDate)
    --Subtact 2880 minutes for each full weekend
        -(DATEDIFF(wk, DATEADD(dd,-1,@StartDate), DATEADD(dd,-1,@EndDate)) * 2880)
    --If StartDate is a Weekend, Subtract time untill monday
        -(CASE WHEN DATENAME(dw, @StartDate) = 'Sunday' THEN DATEDIFF(MI,@StartDate,DATEADD(d,0,DATEDIFF(d,-1,@StartDate))) ELSE 0 END)
        -(CASE WHEN DATENAME(dw, @StartDate) = 'Saturday' THEN DATEDIFF(MI,@StartDate,DATEADD(d,0,DATEDIFF(d,-1,@StartDate))) + 1440 ELSE 0 END)
    --If EndDate is a Weekend, Subtract time since friday
        -(CASE WHEN DATENAME(dw, @EndDate) = 'Saturday' THEN DATEDIFF(mi,CONVERT(varchar(10),@EndDate,112),@EndDate) ELSE 0 END)
        -(CASE WHEN DATENAME(dw, @EndDate) = 'Sunday' THEN DATEDIFF(mi,CONVERT(varchar(10),@EndDate,112),@EndDate) + 1440 ELSE 0 END)
    --Subtract all holidays
        -((SELECT Count(*) 
           FROM SY_Holiday H
           WHERE H.Date BETWEEN @StartDate AND @EndDate
            AND DATEPART(DW,H.Date) NOT IN (6,7)) * 1440)
        )
    END  
GO
编辑:我们还需要考虑假期。这些假期存储在一个表SY_Holiday中。如果假期在周六或周日,那么它是不相关的,不应该扣除,但是如果它在周二周四,那么我们每天将扣除1440。如果假期在周五,那么我们需要从中扣除时间星期四下午5点到星期五下午5点。星期一也一样。这应该意味着扣除1440单元就可以了。

这对我来说很有效:

DECLARE @Swap DATETIME2
DECLARE @Weekend_Start_Time time = '17:00'
DECLARE @Weekend_End_Time time = '08:00'

IF @StartDate > @EndDate
    Select  @Swap = @EndDate, @EndDate = @StartDate, @StartDate = @Swap

    Set @StartDate = DATEADD(DAY, -1, DATEADD(MINUTE, -DATEPART(MINUTE, @Weekend_End_Time), DATEADD(HOUR, -DATEPART(HOUR, @Weekend_End_Time), @StartDate)))
    Set @EndDate = DATEADD(DAY, -1, DATEADD(MINUTE, -DATEPART(MINUTE, @Weekend_End_Time), DATEADD(HOUR, -DATEPART(HOUR, @Weekend_End_Time), @EndDate)))
    Set @Weekend_Start_Time = DATEADD(MINUTE, -DATEPART(MINUTE, @Weekend_End_Time), DATEADD(HOUR, -DATEPART(HOUR, @Weekend_End_Time), @Weekend_Start_Time))

SELECT
    --Start with total number of minutes including weekends
    DATEDIFF(MINUTE,@StartDate, @EndDate)
    --Subtact 2880 minutes for each full weekend
    - (DATEDIFF(wk, @StartDate, @EndDate) * 3780)
    --If StartDate is a Weekend, Subtract time untill monday
    - Coalesce(DATEDIFF(MINUTE,
        DATEADD(HOUR, DATEPART(HOUR, @Weekend_Start_Time) - DATEPART(HOUR, @StartDate),
            DATEADD(MINUTE, DATEPART(MINUTE, @Weekend_Start_Time) - DATEPART(MINUTE, @StartDate),
                DATEADD(d, -Case DATEPART(dw, @StartDate) When 5 then Case When cast(@StartDate as time) > @Weekend_Start_Time then 0 end
                    When 6 then 1 When 7 then 2 End, @StartDate)
                )
            )
        , @StartDate), 0)
    --If EndDate is a Weekend, Subtract time since friday
    - Coalesce(DATEDIFF(MINUTE, 
        DATEADD(HOUR, DATEPART(HOUR, @Weekend_Start_Time) - DATEPART(HOUR, @EndDate),
            DATEADD(MINUTE, DATEPART(MINUTE, @Weekend_Start_Time) - DATEPART(MINUTE, @EndDate),
                DATEADD(d, -Case DATEPART(dw, @EndDate) When 5 then Case When cast(@EndDate as time) > @Weekend_Start_Time then 0 end
                    When 6 then 1 When 7 then 2 End, @EndDate)
                )
            )
        , @EndDate), 0)

请注意,我将2880改为3780。这是从星期五17:00到星期一8:00的分钟数

国定假日和其他非工作日如何?谢谢你提醒我,我忘了提到,这是我们的假期表的目的。这将跟踪这些天,并应从总数中扣除。我编辑了original post突出显示假日。与其实现假日表,为什么不引入日历表?每天一行,20年的行只有~7000行。您可以添加有用的列,如每天工作的开始时间和结束时间,然后此查询简化为仅从该表中查找重叠给定的日期,并对找到的每一天的工作分钟数求和。好的,我会咬一口……我们如何进行比较?感谢您的帮助,如果开始日期和结束日期在周末窗口之外,这很有效。但是,如果我们在窗口内开始计算,则计算结果为负值。例如,“09/11/15 18:30”到“09/12/15 18:30”应该返回0天,但我得到了-90。必须为案例6添加一个额外的条件来表示开始日期,案例=2表示开始日期。我将在今晚晚些时候更新我的答案。谢谢Julien,还要注意假期的要求,我已经更新了原始代码以显示假期逻辑。这与您的数学兼容吗?可以添加Holliday表。这不应该是一个问题e、 我只是删除它,因为它更容易在这里测试。