我有这个示例数据集
ShiftDate Description StartTime EndTime IsWorkShift
2014-01-01 Day Shift 2013-12-31 21:00:00.000 2014-01-01 09:00:00.000 1
2014-01-01 Night Shift 2014-01-01 09:00:00.000 2014-01-01 21:00:00.000 0
2014-01-02 Day Shift 2014-01-01 21:00:00.000 2014-01-02 09:00:00.000 1
2014-01-02 Night Shift 2014-01-02 09:00:00.000 2014-01-02 21:00:00.000 0
2014-01-03 Day Shift 2014-01-02 21:00:00.000 2014-01-03 09:00:00.000 1
2014-01-03 Night Shift 2014-01-03 09:00:00.000 2014-01-03 21:00:00.000 0
2014-01-04 Day Shift 2014-01-03 21:00:00.000 2014-01-04 09:00:00.000 1
2014-01-04 Night Shift 2014-01-04 09:00:00.000 2014-01-04 21:00:00.000 0
2014-01-05 Day Shift 2014-01-04 21:00:00.000 2014-01-05 09:00:00.000 1
2014-01-05 Night Shift 2014-01-05 09:00:00.000 2014-01-05 21:00:00.000 0
我需要在给定StartTime和持续时间
的情况下计算出EndTime例如,如果我提供的开始时间为" 2014-01-01 21:00:00.000"和持续时间24小时
我需要" 2014-01-03 09:00:00.000"作为EndTime返回
2014-01-02 Day Shift 12 Working Hours
2014-01-02 Night Shift 0 Working Hours
2014-01-03 Day Shift 12 Working Hours
我已经使用了光标,但是当我需要使用它进行50次计算时,它变得非常慢。
ALTER FUNCTION [Maintenance].[CalendarDuration]
(
@ServerID INT,
@UTCStartTime DATETIME,
@WorkingDuration INT
)
RETURNS int
AS
BEGIN
DECLARE @UTCEndTime as Datetime;
DECLARE @ShiftStartTime as datetime, @ShiftEndTime as datetime;
DECLARE @ShiftDuration as int;
DECLARE ShiftCursor CURSOR FAST_FORWARD
FOR SELECT t1.StartTime, t1.EndTime
FROM config.WorkingDayShiftPatterns t1
WHERE
t1.ServerID = @ServerID
AND t1.EndTime > @UTCStartTime
AND t1.IsWorkShift = 1
ORDER BY t1.StartTime;
OPEN ShiftCursor;
FETCH NEXT FROM ShiftCursor
INTO @ShiftStartTime, @ShiftEndTime;
WHILE @@FETCH_STATUS = 0
BEGIN
IF @ShiftStartTime < @UTCStartTime
SET @ShiftStartTime = @UTCStartTime;
SET @ShiftDuration = DATEDIFF(minute, @ShiftStartTime, @ShiftEndTime);
IF @ShiftDuration >= @WorkingDuration
BEGIN
SET @UTCEndTime = DATEADD(minute, @WorkingDuration, @ShiftStartTime);
BREAK;
END
ELSE
SET @WorkingDuration = @WorkingDuration - @ShiftDuration;
FETCH NEXT FROM ShiftCursor
INTO @ShiftStartTime, @ShiftEndTime;
END
CLOSE ShiftCursor;
DEALLOCATE ShiftCursor;
RETURN DATEDIFF(minute, @UTCStartTime, @UTCEndTime);
END
答案 0 :(得分:2)
公用表格表达式可以找到每个班次结束时剩余的小时数,这样您就可以轻松选出最后一小时工作的班次;
DECLARE @UTCStartTime DATETIME = '2014-01-01 21:00:00.000';
DECLARE @WorkingDuration INT = 24;
WITH WorkingShifts AS (
SELECT CASE WHEN @UTCStartTime<StartTime
THEN StartTime ELSE @UTCStartTime END StartTime, EndTime,
@WorkingDuration -
SUM(DATEDIFF(HH, CASE WHEN @UTCStartTime<StartTime
THEN StartTime ELSE @UTCStartTime
END, EndTime))
OVER (ORDER BY StartTime) left_after_shift
FROM WorkingDayShiftPatterns
WHERE IsWorkShift=1 AND EndTime >= @UTCStartTime
)
SELECT TOP 1 DATEADD(HH, left_after_shift, EndTime) done_at
FROM WorkingShifts
WHERE left_after_shift <= 0
ORDER BY StartTime;
SQLfiddle有点累,所以这在SQL Server 2014上进行了测试。不要测试任何旧版本,但它应该至少在2012年有效。
答案 1 :(得分:0)
这会有效吗?
select min(EndTime)
from shifts
where EndTime >= DateAdd(hour, @Duration, @StartTime)