Бывает иногда полезной такая функция, рассчитывает количество рабочих часов между датами
Написал функцию давно, но выручала не раз.
DECLARE @startdate datetime
DECLARE @enddate DATETIME
SET @startdate = '2015-04-28 12:33:19.000'
SET @enddate = '2015-04-30 09:45:20.000'
SELECT [dbo].[F_РасчетЧистогоРабочегоВремени] (@startdate, @enddate)
Результат расчета в часах
Текст самой функции
ALTER FUNCTION [dbo].[F_РасчетЧистогоРабочегоВремени]
(
-- Add the parameters for the function here
@ДатаВремяНачала datetime, @ДатаВремяЗавершения datetime
)
RETURNS decimal(20,4)
AS
BEGIN
--DECLARE @ДатаВремяНачала datetime = '2017-08-01 10:31:52.133'
--DECLARE @ДатаВремяЗавершения datetime = '2017-08-04 16:50:49.420'
DECLARE @НачалоРабочегоДня time = '10:00:00',
@КонецРабочегоДня time = '19:00:00',
@ДатаНачала datetime = cast(cast( @ДатаВремяНачала as date) as datetime),
@ДатаЗавершения datetime = cast(cast( @ДатаВремяЗавершения as date)as datetime),
@ВсегоМинут AS INT
--ДОЛЖЕН БЫТЬ ИНДЕКС ПО ДАТЕ НА ТАБЛИЦЕ Кластерный!!!!!
select @ВсегоМинут = sum( IIF(Длительность<0,0,Длительность))
from
(
select d.*, isnull(datediff(MI, НачалоРабочегоДня,КонецРабочегоДня),0) Длительность
from
(
select d.Дата , d.[Рабочий День] ,
IIF(НачалоРабочегоДня <НачалоРабочегоДня2, НачалоРабочегоДня2, НачалоРабочегоДня) НачалоРабочегоДня ,
IIF(КонецРабочегоДня >КонецРабочегоДня2, КонецРабочегоДня2, КонецРабочегоДня) КонецРабочегоДня
from
(
SELECT Дата , [Рабочий День] ,
case when Дата = @ДатаНачала then @ДатаВремяНачала else Дата + cast(@НачалоРабочегоДня as datetime) end НачалоРабочегоДня ,
case when Дата = @ДатаЗавершения then @ДатаВремяЗавершения else Дата + cast(@КонецРабочегоДня as datetime) end КонецРабочегоДня,
Дата + cast(@НачалоРабочегоДня as datetime) as НачалоРабочегоДня2,
Дата + cast(@КонецРабочегоДня as datetime) as КонецРабочегоДня2
FROM [dbo].[T_DP_Дата] d (NOLOCK)
WHERE Дата BETWEEN @ДатаНачала AND @ДатаЗавершения
AND [Рабочий День] = 1
) d
)d
) d
--select @ВсегоМинут/60.
-- Return the result of the function
RETURN @ВсегоМинут/60.
END
(
-- Add the parameters for the function here
@ДатаВремяНачала datetime, @ДатаВремяЗавершения datetime
)
RETURNS decimal(20,4)
AS
BEGIN
--DECLARE @ДатаВремяНачала datetime = '2017-08-01 10:31:52.133'
--DECLARE @ДатаВремяЗавершения datetime = '2017-08-04 16:50:49.420'
DECLARE @НачалоРабочегоДня time = '10:00:00',
@КонецРабочегоДня time = '19:00:00',
@ДатаНачала datetime = cast(cast( @ДатаВремяНачала as date) as datetime),
@ДатаЗавершения datetime = cast(cast( @ДатаВремяЗавершения as date)as datetime),
@ВсегоМинут AS INT
--ДОЛЖЕН БЫТЬ ИНДЕКС ПО ДАТЕ НА ТАБЛИЦЕ Кластерный!!!!!
select @ВсегоМинут = sum( IIF(Длительность<0,0,Длительность))
from
(
select d.*, isnull(datediff(MI, НачалоРабочегоДня,КонецРабочегоДня),0) Длительность
from
(
select d.Дата , d.[Рабочий День] ,
IIF(НачалоРабочегоДня <НачалоРабочегоДня2, НачалоРабочегоДня2, НачалоРабочегоДня) НачалоРабочегоДня ,
IIF(КонецРабочегоДня >КонецРабочегоДня2, КонецРабочегоДня2, КонецРабочегоДня) КонецРабочегоДня
from
(
SELECT Дата , [Рабочий День] ,
case when Дата = @ДатаНачала then @ДатаВремяНачала else Дата + cast(@НачалоРабочегоДня as datetime) end НачалоРабочегоДня ,
case when Дата = @ДатаЗавершения then @ДатаВремяЗавершения else Дата + cast(@КонецРабочегоДня as datetime) end КонецРабочегоДня,
Дата + cast(@НачалоРабочегоДня as datetime) as НачалоРабочегоДня2,
Дата + cast(@КонецРабочегоДня as datetime) as КонецРабочегоДня2
FROM [dbo].[T_DP_Дата] d (NOLOCK)
WHERE Дата BETWEEN @ДатаНачала AND @ДатаЗавершения
AND [Рабочий День] = 1
) d
)d
) d
--select @ВсегоМинут/60.
-- Return the result of the function
RETURN @ВсегоМинут/60.
END