如何在这种情况下排除周末并仅在给定日期之间获得时间差异,下面是方案。
declare @d1 datetime, @d2 datetime
select @d1 = '2017-08-10 19:51:01.000', @d2 = '2017-08-16 17:52:14.000'
select
Convert(varchar(5),datediff(s, @d1, @d2)/3600 - (datediff(wk, @d1, @d2) * 2) -
case when datepart(dw, @d1) = 1 then 24 else 0 end +
case when datepart(dw, @d2) = 1 then 24 else 0 end )
+':'+
convert(Varchar(5),datediff(s, @d1, @d2)%3600/60 - (datediff(wk, @d1, @d2) * 2) -
case when datepart(dw, @d1) = 1 then 24 else 0 end +
case when datepart(dw, @d2) = 1 then 24 else 0 end)
+':'+
convert(Varchar(5),datediff(s, @d1, @d2)%60 - (datediff(wk, @d1, @d2) * 2) -
case when datepart(dw, @d1) = 1 then 24 else 0 end +
case when datepart(dw, @d2) = 1 then 24 else 0 end
) as hrs
答案 0 :(得分:0)
一个想法是在@ d1之前或之后以及@ d2之前的上周一找到第一个星期一(如果我们说“周末”意味着星期六和星期日)。这是整周的数量。所以一周的时间是120(5天* 24小时)。然后我们将在上周一之后添加小时数直到@ d2。一个简单的案例在@ d2周的某一天将允许您在上周处理周末。同样,我们将计算@ d1和第一个星期一之前的小时数。
declare @d1 datetime, @d2 datetime
select @d1 = '2017-08-10 19:51:01.000', @d2 = '2017-08-16 17:52:14.000'
declare @StartOfFirstWeekAfterStartDate date = cast(dateadd(day, case datepart(weekday, @d1)
when 1 /* Sunday */ then -6
when 2 /* Monday */ then 0
when 3 /* Tuesday */ then 6
when 4 /* Wendsday */ then 5
when 5 /* Thursday */ then 4
when 6 /* Friday */ then 3
when 7 /* Saturday */ then 2
end, @d1) as date),
@StartOfLastWeekBeforeEndDate date = cast(dateadd(day, case datepart(weekday, @d2)
when 1 /* Sunday */ then -6
when 2 /* Monday */ then 0
when 3 /* Tuesday */ then -1
when 4 /* Wendsday */ then -2
when 5 /* Thursday */ then -3
when 6 /* Friday */ then -4
when 7 /* Saturday */ then -5
end, @d2) as date)
declare @NumberOfWorkdays int = datediff(week, @StartOfFirstWeekAfterStartDate, @StartOfLastWeekBeforeEndDate) * 5
declare @HoursWeekBefore int = case datepart(weekday, @d1)
when 1 /* Sunday */ then 0
when 2 /* Monday */ then 5 * 24 - datepart(hour, @d1)
when 3 /* Tuesday */ then 4 * 24 - datepart(hour, @d1)
when 4 /* Wendsday */ then 3 * 24 - datepart(hour, @d1)
when 5 /* Thursday */ then 2 * 24 - datepart(hour, @d1)
when 6 /* Friday */ then 1 * 24 - datepart(hour, @d1)
when 7 /* Saturday */ then 0
end
declare @HoursWeekAfter int = case datepart(weekday, @d2)
when 1 /* Sunday */ then 5 * 24
when 2 /* Monday */ then 0 * 24 + datepart(hour, @d2)
when 3 /* Tuesday */ then 1 * 24 + datepart(hour, @d2)
when 4 /* Wendsday */ then 2 * 24 + datepart(hour, @d2)
when 5 /* Thursday */ then 3 * 24 + datepart(hour, @d2)
when 6 /* Friday */ then 4 * 24 + datepart(hour, @d2)
when 7 /* Saturday */ then 5 * 24
end
declare @HoursDiff int = @HoursWeekBefore + @NumberOfWorkdays * 24 + @HoursWeekAfter
select
@StartOfFirstWeekAfterStartDate,
datepart(WEEKDAY, @StartOfFirstWeekAfterStartDate), -- Should always be Monday
@StartOfLastWeekBeforeEndDate,
datepart(WEEKDAY, @StartOfLastWeekBeforeEndDate), -- Should always be Monday
@NumberOfWorkdays,
datediff(week, @StartOfFirstWeekAfterStartDate, @StartOfLastWeekBeforeEndDate),
@HoursWeekBefore,
@HoursWeekAfter,
@HoursDiff
上面的代码适合sp / udf使用。如果我们将所有这些计算放在一个表达式中,它将成为:
declare @d1 datetime, @d2 datetime
select @d1 = '2017-08-10 19:51:01.000', @d2 = '2017-08-16 17:52:14.000'
select case datepart(weekday, @d1)
when 1 /* Sunday */ then 0
when 2 /* Monday */ then 5 * 24 - datepart(hour, @d1)
when 3 /* Tuesday */ then 4 * 24 - datepart(hour, @d1)
when 4 /* Wendsday */ then 3 * 24 - datepart(hour, @d1)
when 5 /* Thursday */ then 2 * 24 - datepart(hour, @d1)
when 6 /* Friday */ then 1 * 24 - datepart(hour, @d1)
when 7 /* Saturday */ then 0
end /* @HoursWeekBefore */
+
datediff(week,
cast(dateadd(day, case datepart(weekday, @d1)
when 1 /* Sunday */ then -6
when 2 /* Monday */ then 0
when 3 /* Tuesday */ then 6
when 4 /* Wendsday */ then 5
when 5 /* Thursday */ then 4
when 6 /* Friday */ then 3
when 7 /* Saturday */ then 2
end, @d1) as date) /* @StartOfFirstWeekAfterStartDate */,
cast(dateadd(day, case datepart(weekday, @d2)
when 1 /* Sunday */ then -6
when 2 /* Monday */ then 0
when 3 /* Tuesday */ then -1
when 4 /* Wendsday */ then -2
when 5 /* Thursday */ then -3
when 6 /* Friday */ then -4
when 7 /* Saturday */ then -5
end, @d2) as date) /* @StartOfLastWeekBeforeEndDate */) * 5 /* @NumberOfWorkdays */ * 24
+
case datepart(weekday, @d2)
when 1 /* Sunday */ then 5 * 24
when 2 /* Monday */ then 0 * 24 + datepart(hour, @d2)
when 3 /* Tuesday */ then 1 * 24 + datepart(hour, @d2)
when 4 /* Wendsday */ then 2 * 24 + datepart(hour, @d2)
when 5 /* Thursday */ then 3 * 24 + datepart(hour, @d2)
when 6 /* Friday */ then 4 * 24 + datepart(hour, @d2)
when 7 /* Saturday */ then 5 * 24
end /* @HoursWeekAfter */
请注意,上述计算取决于DATEFIRST设置。我写的假设周日是一周的第一天(即datepart(工作日,@今天)将返回2)。如果不是这种情况,则应调整case语句中的偏移量。 我也没有在这些时间处理分钟,因此小时计算有点粗糙。如果这是一个问题,您可以使用上述方法计算@ d1和@ d2之间的分钟数,并将其除以60.
答案 1 :(得分:0)
create function DateDiffWeekends(@a date, @b date)
returns int as
BEGIN
DECLARE @Result int
SELECT @Result = DateDiff(dd,@a,@b)
- DateDiff(ww,@a,@b)*2
- case DatePart(dw,@a) when 1 then 1 else 0 end
- case DatePart(dw,@b) when 7 then 1 else 0 end
RETURN @Result
End
这是(类似于)我正在使用生产环境的功能。我将分析SELECT @Result
区域中的四个公式中的每个公式正在做什么。
DateDiff(dd,@a,@b)
这只是查找两个日期之间的天数。经典DateDiff。
- DateDiff(ww,@a,@b)*2
这会查找两天之间的周数,并将其乘以2。这有效的原因是因为它计算了周休息的次数,而不是“7天段”的数量。例如,如果我选择星期五和随后的星期一的日期,DateDiff(ww,$Saturday,$Monday)
将返回1周,即使它们仅在技术上相隔2天。
- case DatePart(dw,@a) when 1 then 1 else 0 end
如果您选择星期日的开始日期,那么您将需要再休息一天。如果您的开始日是星期六,那么它将在不同的一周,所以之前的声明将照顾它。
- case DatePart(dw,@b) when 7 then 1 else 0 end
如果您选择星期六的结束日期,那么您还需要从结果中休息一天。如果你的结束日是星期天,它将再次出现在不同的一周。
如果你想测试/玩它,这是一个SQLFiddle。
编辑:我刚注意到你还要求时间。我将在这里留下这个答案,以防它对其他人有用,但它可能不适用于你的情况。