SQL-获取2个datetime之间的分钟数,但仅限于工作日
我需要得到两次约会之间的分钟数。问题是我只需要计算一周中的分钟数。我的周末时间不算在内。另外,我们将周末定义为从周五下午5点开始到周一上午8点结束。我相信我已经创建了一个函数来计算一周中的时间,但它不计算星期五17:00-23:59和星期一00:00-7:59之间的时间。此计算可能跨越多个星期,因此需要每周过滤掉此时间 预期结果的一些例子如下: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分钟(周
- 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、 我只是删除它,因为它更容易在这里测试。