从 StartTime 和 EndTime 计算 Shift 的 SQL 函数
Posted
技术标签:
【中文标题】从 StartTime 和 EndTime 计算 Shift 的 SQL 函数【英文标题】:SQL Function that calculates Shift from StartTime and EndTime 【发布时间】:2011-01-28 09:01:27 【问题描述】:我一直在尝试使用一个函数来计算员工从 StartTime 和 EndTime 开始工作的时间。这是我到目前为止的代码,似乎计算移位错误。
Shift 1 from 08:00:00 - 16:30:00
Shift 2 from 16:00:00 - 00:30:00
Shift 3 from 00:00:00 - 08:30:00
另外,工作时间最多的班次在班次之间的时间段中获胜。
谢谢, G
`FUNCTION [dbo].[ShiftDifferential] (
@StartTime time(0),
@EndTime time(0)
)
RETURNS int
AS
BEGIN
--DECLARE @StartTime time(0)
--DECLARE @EndTime time(0)
-- Declare the return variable here
DECLARE @Shift1StartTime time(0)
DECLARE @Shift2StartTime time(0)
DECLARE @Shift3StartTime time(0)
DECLARE @Shift1EndTime time(0)
DECLARE @Shift2EndTime time(0)
DECLARE @Shift3EndTime time(0)
DECLARE @HrsShift1 decimal(18,2)
DECLARE @HrsShift2 decimal(18,2)
DECLARE @HrsShift3 decimal(18,2)
DECLARE @ShiftDiff int
--SET @StartTime = '09:00:00'
--SET @EndTime = '13:00:00'
SET @Shift1StartTime = '08:00:00'
SET @Shift2StartTime = '16:00:00'
SET @Shift3StartTime = '00:00:00'
SET @Shift1EndTime = '16:30:00'
SET @Shift2EndTime = '00:30:00'
SET @Shift3EndTime = '08:30:00'
--SELECT DATEDIFF(HH, @Shift1StartTime, @EndTime)
-- hours are between shift 3 and shift 1
if DATEDIFF(HH, @Shift1StartTime, @StartTime) < 0 AND (DATEDIFF(hh, @Shift1StartTime, @EndTime) < 8.0 AND DATEDIFF(hh, @Shift1StartTime, @EndTime) > 0)
begin
--PRINT 'Shift 3-1 step1'
SET @HrsShift3 = DATEDIFF(HH, @StartTime, @Shift1StartTime)
SET @HrsShift1 = DATEDIFF(HH, @Shift1StartTime, @Endtime)
--PRINT @HrsShift3
--PRINT @HrsShift1
-- get shift with most hours
if @HrsShift3 > @HrsShift1
begin
SET @ShiftDiff = 3
end
else
begin
SET @ShiftDiff = 1
end
end
-- hours are in shift 1
if (DATEDIFF(HH, @Shift1StartTime, @StartTime) = 0 AND DATEDIFF(HH, @Shift1StartTime, @EndTime) <= 8)
OR (DATEDIFF(HH, @Shift1StartTime, @StartTime) > 0 AND DATEDIFF(HH, @Shift1StartTime, @EndTime) <= 8)
begin
--PRINT 'Shift 1 step2'
SET @HrsShift3 = 0
SET @HrsShift1 = DATEDIFF(HH, @StartTime, @EndTime)
--PRINT @HrsShift3
--PRINT @HrsShift1
-- only one shift with hours
SET @ShiftDiff = 1
end
-- hours are between shift 1 and shift 2
if DATEDIFF(HH, @Shift2StartTime, @StartTime) < 0 and (DATEDIFF(HH, @Shift2StartTime, @EndTime) < 8.0 AND DATEDIFF(HH, @Shift2StartTime, @EndTime) > 0)
begin
--PRINT 'Shift 1-2 step1'
SET @HrsShift1 = DATEDIFF(HH, @StartTime, @Shift2StartTime)
SET @HrsShift2 = DATEDIFF(HH, @Shift2StartTime, @Endtime)
--PRINT @HrsShift1
--PRINT @HrsShift2
-- get the shift with most hours
if @HrsShift1 > @HrsShift2
begin
SET @ShiftDiff = 1
end
else
begin
SET @ShiftDiff = 2
end
end
-- hours are in shift 2
if (DATEDIFF(HH, @Shift2StartTime, @StartTime) = 0 AND DATEDIFF(HH, @Shift2StartTime, @EndTime) <= 8)
OR (DATEDIFF(HH, @Shift2StartTime, @StartTime) > 0 AND DATEDIFF(HH, @Shift2StartTime, @EndTime) <= 8)
begin
--PRINT 'Shift 2 step2'
SET @HrsShift3 = 0
SET @HrsShift1 = DATEDIFF(HH, @StartTime, @EndTime)
--PRINT @HrsShift3
--PRINT @HrsShift1
-- only one shift with hours
SET @ShiftDiff = 2
end
-- hours are between shift 2 and shift 3 - overnight shift
if DATEDIFF(HH, @StartTime, @EndTime) < 0
begin
--PRINT 'Shift 2-3 step1'
SET @HrsShift2 = DATEDIFF(HH, @StartTime, '23:59:59') + DATEDIFF(HH, '00:00:00', '00:30:00')
SET @HrsShift3 = DATEDIFF(HH, '00:30:00', @EndTime)
--PRINT @HrsShift2
--PRINT @HrsShift3
-- get the shift with most hours
if @HrsShift2 > @HrsShift3
begin
SET @ShiftDiff = 2
end
else
begin
SET @ShiftDiff = 3
end
end
-- hours are in shift 3
if (DATEDIFF(HH, @Shift3StartTime, @StartTime) = 0 AND DATEDIFF(HH, @Shift3StartTime, @EndTime) <= 8)
OR (DATEDIFF(HH, @Shift3StartTime, @StartTime) > 0 AND DATEDIFF(HH, @Shift3StartTime, @EndTime) <= 8)
begin
--PRINT 'Shift 3 step2'
SET @HrsShift2 = 0
SET @HrsShift3 = DATEDIFF(HH, @StartTime, @EndTime)
--PRINT @HrsShift2
--PRINT @HrsShift3
-- only one shift with hours
SET @ShiftDiff = 3
end
RETURN @ShiftDiff;
END`
【问题讨论】:
【参考方案1】:感觉就像您正在尝试对基于集合的问题采用迭代方法。
在我看来,您正试图找出与时间表条目中输入的时间重叠最多的班次。
解决这个问题,您会发现它非常基于集合,并且可以轻松扩展,因为如果您愿意,可以使用时间表来代替。这假设事情开始使用time
类型,但我将其转换为datetime
,因为班次可能会在第二天结束。
with
Shifts as
(
SELECT ShiftID, cast(StartTime as datetime) as StartTime,
case
when EndTime < StartTime
then dateadd(day,1,cast(EndTime as datetime))
else cast(EndTime as datetime)
end as EndTime
FROM Shifts
),
Times as
(select 1 as TimeID,
cast(@StartTime as datetime) as StartTime,
case
when @EndTime < @StartTime
then dateadd(day,1,cast(@EndTime as datetime))
else cast(@EndTime as datetime)
end as EndTime
),
Overlaps as
(
select s.ShiftID, t.TimeID,
case when s.StartTime > t.StartTime then s.StartTime else t.StartTime end as StartOverlap,
case when s.EndTime < t.EndTime then s.EndTime else t.EndTime end as EndOverlap,
from Shifts s
cross join Times t
),
OrderedOverlaps as
(
select *, row_number() over(partition by TimeID order by datediff(min,StartOverlap,EndOverlap) desc) as RowNum
from Overlaps
)
select s.ShiftID, t.TimeID
from OrderedOverlaps
where RowNum = 1;
【讨论】:
您好 Rob 感谢您的快速回复。我测试了一些案例,代码看起来不错。但是我在夜班时遇到了麻烦,例如。这应该给班次 3,因为大部分工作时间都在班次 3 上。`SET @StartTime = '22:00:00' SET @EndTime = '03:30:00' 另外第一个选择语句'FROM Shifts'是我的表持有 ShiftID 和 StartTime / EndTime 信息? datediff(min,StartOverlap,EndOverlap) 你的意思是 datediff(mi,StartOverlap,EndOverlap) 对吧? G 啊,是的。我的意思是分钟。你是对的,可能应该有一些代码将“下一天班”放入其中。比如: union all SELECT ShiftID, dateadd(day, 1, cast(StartTime as datetime)) as StartTime, dateadd(day,1 ,当 EndTime 很棒的方法。效果很好。再次感谢 G以上是关于从 StartTime 和 EndTime 计算 Shift 的 SQL 函数的主要内容,如果未能解决你的问题,请参考以下文章
Google Calendar API 的 VacationSettings 类型的 startTime 和 endTime 是啥时区?