Я понимаю, что разные решения будут иметь разные вариации того, что означает «рабочие дни», но в моем случае я имею в виду с понедельника по пятницу включительно.
По сути, я создал функцию для расчета за меня, и мое текущее решение работает. Моя проблема (и причина для того, чтобы задать этот вопрос) заключается в том, что я обеспокоен тем, что это плохой способ достижения этого, потому что функция вызывается с очень высокой частотой. За последние 3 месяца он был вызван 12 миллионов раз в производственной системе, со средним рабочим временем 44 мс.
Это заставляет меня задаться вопросом, является ли это правильным способом достижения решения.
Во-первых, вот функция, которую я создал:
CREATE FUNCTION [dbo].[fn_WorkDays]
(
@StartDate DATETIME,
@EndDate DATETIME = NULL --@EndDate replaced by @StartDate when DEFAULTed
)
RETURNS INT
AS
BEGIN
--===== Declare local variables
--Temporarily holds @EndDate during date reversal
DECLARE @Swap DATETIME
--===== If the Start Date is null, return a NULL and exit
IF @StartDate IS NULL
RETURN NULL
--===== If the End Date is null, populate with Start Date value
-- so will have two dates (required by DATEDIFF below)
IF @EndDate IS NULL
SELECT @EndDate = @StartDate
--===== Strip the time element from both dates (just to be safe) by converting
-- to whole days and back to a date. Usually faster than CONVERT.
-- 0 is a date (01/01/1900 00:00:00.000)
SELECT @StartDate = DATEADD(dd,DATEDIFF(dd,0,@StartDate),0),
@EndDate = DATEADD(dd,DATEDIFF(dd,0,@EndDate) ,0)
--===== If the inputs are in the wrong order, reverse them
IF @StartDate > @EndDate
SELECT @Swap = @EndDate,
@EndDate = @StartDate,
@StartDate = @Swap
--===== Calculate and return the number of workdays using the
-- input parameters. This is the meat of the function.
-- This is really just one formula with a couple of parts
-- that are listed on separate lines for documentation
-- purposes.
RETURN (
SELECT
--Start with total number of days including weekends
(DATEDIFF(dd,@StartDate,@EndDate)+1)
--Subtact 2 days for each full weekend
-(DATEDIFF(wk,@StartDate,@EndDate)*2)
--If StartDate is a Sunday, Subtract 1
-(CASE WHEN DATENAME(dw,@StartDate) = 'Sunday'
THEN 1
ELSE 0
END)
--If EndDate is a Saturday, Subtract 1
-(CASE WHEN DATENAME(dw,@EndDate) = 'Saturday'
THEN 1
ELSE 0
END)
)
END
В качестве простого примера его использования я бы запустил запрос такого типа:
SELECT MYTABLE.EntryDate
,dbo.fn_WorkDays(MYTABLE.EntryDate, getutcdate()) as WorkingDays
FROM MYTABLE
MyTable может содержать 5000 строк с разными датами в столбце EntryDate (5000 вызовов функции)
У меня вопрос: я что-то здесь упускаю из-за того, как я это делаю, было бы полезно создать для этого справочную таблицу (но это много комбинаций дат)
Любые мысли, улучшения или рекомендации будут оценены ...