我希望在SQL Server中获得两个工作日之间以秒为单位的差异。我们的日期表包含IsWorkingDay标志,如果结束日期为null,则默认为getdate()。工作日开始于上午8点,结束于下午4:30。
我有以下查询,需要其他部分的帮助。
@StartDate和@EndDate并不总是在工作日。如果@StartDate在任何周末或假日,则应汇总到下一个工作日的上午8:00。如果@EndDate在任何周末或假日,则应累积到最后一个工作日下午4:30。
CREATE FUNCTION TimeDiffInSeconds
(
@Startdate DATETIME
,@EndDate DATETIME
)
RETURNS INT
AS
BEGIN
DECLARE @WorkSeconds INT = 0;
DECLARE @Reverse BIT;
DECLARE @StartHour FLOAT = 8
DECLARE @EndHour FLOAT = 16.50
IF @Startdate > @EndDate
BEGIN
DECLARE @TempDate DATETIME = @Startdate;
SET @Startdate = @EndDate;
SET @EndDate = @TempDate;
SET @Reverse = 1;
END;
ELSE
SET @Reverse = 0;
IF DATEPART(HH, @StartDate) < @StartHour
SET @StartDate = DATEADD(HOUR, @StartHour, DATEDIFF(DAY, 0, @StartDate));
IF DATEPART(HH, @StartDate) >= @EndHour + 1
SET @StartDate = DATEADD(HOUR, @StartHour + 24, DATEDIFF(DAY, 0, @StartDate));
IF DATEPART(HH, @EndDate) >= @EndHour + 1
SET @EndDate = DATEADD(HOUR, @EndHour, DATEDIFF(DAY, 0, @EndDate));
IF DATEPART(HH, @EndDate) < @StartHour
SET @EndDate = DATEADD(HOUR, @EndHour - 24, DATEDIFF(DAY, 0, @EndDate));
IF @Startdate > @EndDate
RETURN 0;
IF DATEDIFF(DAY, @StartDate, @EndDate) <= 0
BEGIN
IF @Startdate <> (SELECT date_id FROM Final.Date WHERE IsWorkingDay = 0)
SET @WorkSeconds = DATEDIFF(ss, @StartDate, @EndDate); -- Calculate difference
ELSE RETURN 0;
END;
ELSE
--need help
RETURN @WorkSeconds;
END
答案 0 :(得分:1)
可以用一种简单的方法来计算。
如果您的两个参数已经是工作日,则您可以按秒返回它们的差异,即每天的差异(每次越过午夜边界)减去-15.5小时(16:30到08:00),减去8,两个日期之间的每个非工作日为5小时(8:00到16:30)。
PS:我已经更新了答案,所以现在我们首先检查@StartDate和@EndDate是否正确的工作日期时间,如果不是,则将其移至正确的日期。之后,您可以应用前面所述的计算时间(以秒为单位)。
CREATE FUNCTION TimeDiffInSeconds
(
@Startdate datetime,
@EndDate datetime
)
RETURNS INT
AS
BEGIN
set @EndDate = coalesce(@EndDate, getdate());
-- We check that @StartDate is a working datetime, and if not we set it to the next one
if convert(time, @StartDate) < convert(time, '08:00')
begin
set @StartDate = convert(datetime, convert(date, @StartDate)) +
convert(datetime, '08:00')
end
if convert(time, @StartDate) > convert(time, '16:30') or
(select IsWorkingDay
from Final.Date
where date_id = convert(date, @StartDate)) = 0
begin
select top 1 @StartDate = convert(datetime, date_id) +
convert(datetime, '08:00')
from Final.Date
where date_id > @StartDate and IsWorkingDay = 1
order by date_id
end
-- We check that @EndDate is a working datetime, and if not we set it to the last one
if convert(time, @EndDate) > convert(time, '16:30')
begin
set @EndDate = convert(datetime, convert(date, @EndDate)) +
convert(datetime, '16:30')
end
if convert(time, @EndDate) < convert(time, '08:00') or
(select IsWorkingDay
from Final.Date
where date_id = convert(date, @EndDate)) = 0
begin
select top 1 @EndDate = convert(datetime, date_id) +
convert(datetime, '16:30')
from Final.Date
where date_id < @EndDate and IsWorkingDay = 1
order by date_id desc
end
-- We return the working time difference in seconds between @StartDate and @EndDate
RETURN datediff(second, @StartDate, @EndDate) -
((15.5 * datediff(day, @StartDate, @EndDate) * 60 * 60) -
(8.5 * (select count(*)
from Final.Date
where IsWorkingDay = 0 and
(date_id between @StartDate and @EndDate or date_id between @EndDate and @StartDate)
) * 60 * 60));
END