Contar dias de trabalho entre duas datas

Como posso calcular o número de dias úteis entre duas datas no SQL Server?

De segunda a sexta e deve ser o T-SQL.

Para dias úteis, de segunda a sexta-feira, você pode fazer isso com um único SELECT, assim:

DECLARE @StartDate DATETIME DECLARE @EndDate DATETIME SET @StartDate = '2008/10/01' SET @EndDate = '2008/10/31' SELECT (DATEDIFF(dd, @StartDate, @EndDate) + 1) -(DATEDIFF(wk, @StartDate, @EndDate) * 2) -(CASE WHEN DATENAME(dw, @StartDate) = 'Sunday' THEN 1 ELSE 0 END) -(CASE WHEN DATENAME(dw, @EndDate) = 'Saturday' THEN 1 ELSE 0 END) 

Se você quiser include feriados, você tem que trabalhar um pouco …

Em Calculating Work Days, você pode encontrar um bom artigo sobre este assunto, mas como você pode ver, ele não é tão avançado.

 --Changing current database to the Master database allows function to be shared by everyone. USE MASTER GO --If the function already exists, drop it. IF EXISTS ( SELECT * FROM dbo.SYSOBJECTS WHERE ID = OBJECT_ID(N'[dbo].[fn_WorkDays]') AND XType IN (N'FN', N'IF', N'TF') ) DROP FUNCTION [dbo].[fn_WorkDays] GO CREATE FUNCTION dbo.fn_WorkDays --Presets --Define the input parameters (OK if reversed by mistake). ( @StartDate DATETIME, @EndDate DATETIME = NULL --@EndDate replaced by @StartDate when DEFAULTed ) --Define the output data type. RETURNS INT AS --Calculate the RETURN of the function. 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 GO 

Se você precisar usar um calendar personalizado, talvez seja necessário adicionar algumas verificações e alguns parâmetros. Espero que seja um bom ponto de partida.

Todos os créditos para Bogdan Maxim & Peter Mortensen. Este é o seu post, acabei de adicionar feriados para a function (Isso pressupõe que você tem uma tabela “tblHolidays” com um campo de data e hora “HolDate”.

 --Changing current database to the Master database allows function to be shared by everyone. USE MASTER GO --If the function already exists, drop it. IF EXISTS ( SELECT * FROM dbo.SYSOBJECTS WHERE ID = OBJECT_ID(N'[dbo].[fn_WorkDays]') AND XType IN (N'FN', N'IF', N'TF') ) DROP FUNCTION [dbo].[fn_WorkDays] GO CREATE FUNCTION dbo.fn_WorkDays --Presets --Define the input parameters (OK if reversed by mistake). ( @StartDate DATETIME, @EndDate DATETIME = NULL --@EndDate replaced by @StartDate when DEFAULTed ) --Define the output data type. RETURNS INT AS --Calculate the RETURN of the function. 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) --Subtract all holidays -(Select Count(*) from [DB04\DB04].[Gateway].[dbo].[tblHolidays] where [HolDate] between @StartDate and @EndDate ) ) END GO -- Test Script /* declare @EndDate datetime= dateadd(m,2,getdate()) print @EndDate select [Master].[dbo].[fn_WorkDays] (getdate(), @EndDate) */ 

Minha versão da resposta aceita como uma function usando DATEPART , então eu não tenho que fazer uma comparação de string na linha com

 DATENAME(dw, @StartDate) = 'Sunday' 

Enfim, aqui está a minha function datediff de negócios

 SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE FUNCTION BDATEDIFF ( @startdate as DATETIME, @enddate as DATETIME ) RETURNS INT AS BEGIN DECLARE @res int SET @res = (DATEDIFF(dd, @startdate, @enddate) + 1) -(DATEDIFF(wk, @startdate, @enddate) * 2) -(CASE WHEN DATEPART(dw, @startdate) = 1 THEN 1 ELSE 0 END) -(CASE WHEN DATEPART(dw, @enddate) = 7 THEN 1 ELSE 0 END) RETURN @res END GO 

Outra abordagem para calcular dias úteis é usar um loop WHILE que basicamente repete um intervalo de datas e o incrementa em 1 sempre que os dias forem encontrados entre segunda e sexta-feira. O script completo para calcular os dias úteis usando o loop WHILE é mostrado abaixo:

 CREATE FUNCTION [dbo].[fn_GetTotalWorkingDaysUsingLoop] (@DateFrom DATE, @DateTo  DATE ) RETURNS INT AS    BEGIN        DECLARE @TotWorkingDays INT= 0;        WHILE @DateFrom <= @DateTo            BEGIN                IF DATENAME(WEEKDAY, @DateFrom) IN('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday')                    BEGIN                        SET @TotWorkingDays = @TotWorkingDays + 1;                END;                SET @DateFrom = DATEADD(DAY, 1, @DateFrom);            END;        RETURN @TotWorkingDays;    END; GO 

Embora a opção loop WHILE seja mais limpa e use menos linhas de código, ela tem o potencial de ser um gargalo de desempenho em seu ambiente, especialmente quando o intervalo de datas se estende por vários anos.

Você pode ver mais methods sobre como calcular dias e horas de trabalho neste artigo: https://www.sqlshack.com/how-to-calculate-work-days-and-hours-in-sql-server/

(Eu sou alguns pontos tímidos de comentar privilégios)

Se você decidir abrir mão do dia de +1 na solução elegante do CMS , observe que, se sua data de início e de término estiverem no mesmo fim de semana, você receberá uma resposta negativa. Ou seja, 2008/10/26 a 2008/10/26 retorna -1.

minha solução simplista:

 select @Result = (..CMS's answer..) if (@Result < 0) select @Result = 0 RETURN @Result 

.. que também define todos os posts errados com data de início após a data de término para zero. Algo que você pode ou não estar procurando.

Para a diferença entre as datas, incluindo feriados eu fui assim:

1) Tabela com feriados:

  CREATE TABLE [dbo].[Holiday]( [Id] [int] IDENTITY(1,1) NOT NULL, [Name] [nvarchar](50) NULL, [Date] [datetime] NOT NULL) 

2) Eu tive minha tabela de planejamentos assim e queria preencher a coluna Work_Days que estava vazia:

  CREATE TABLE [dbo].[Plan_Phase]( [Id] [int] IDENTITY(1,1) NOT NULL, [Id_Plan] [int] NOT NULL, [Id_Phase] [int] NOT NULL, [Start_Date] [datetime] NULL, [End_Date] [datetime] NULL, [Work_Days] [int] NULL) 

3) Assim, a fim de obter “Work_Days” para mais tarde preencher minha coluna só tinha que:

 SELECT Start_Date, End_Date, (DATEDIFF(dd, Start_Date, End_Date) + 1) -(DATEDIFF(wk, Start_Date, End_Date) * 2) -(SELECT COUNT(*) From Holiday Where Date >= Start_Date AND Date <= End_Date) -(CASE WHEN DATENAME(dw, Start_Date) = 'Sunday' THEN 1 ELSE 0 END) -(CASE WHEN DATENAME(dw, End_Date) = 'Saturday' THEN 1 ELSE 0 END) -(CASE WHEN (SELECT COUNT(*) From Holiday Where Start_Date = Date) > 0 THEN 1 ELSE 0 END) -(CASE WHEN (SELECT COUNT(*) From Holiday Where End_Date = Date) > 0 THEN 1 ELSE 0 END) AS Work_Days from Plan_Phase 

Espero que eu possa ajudar.

Felicidades

  DECLARE @TotalDays INT,@WorkDays INT DECLARE @ReducedDayswithEndDate INT DECLARE @WeekPart INT DECLARE @DatePart INT SET @TotalDays= DATEDIFF(day, @StartDate, @EndDate) +1 SELECT @ReducedDayswithEndDate = CASE DATENAME(weekday, @EndDate) WHEN 'Saturday' THEN 1 WHEN 'Sunday' THEN 2 ELSE 0 END SET @TotalDays=@TotalDays-@ReducedDayswithEndDate SET @WeekPart=@TotalDays/7; SET @DatePart=@TotalDays%7; SET @WorkDays=(@WeekPart*5)+@DatePart RETURN @WorkDays 

Aqui está uma versão que funciona bem (eu acho). A tabela de feriados contém as colunas Holiday_date que contêm feriados que sua empresa observa.

 DECLARE @RAWDAYS INT SELECT @RAWDAYS = DATEDIFF(day, @StartDate, @EndDate )--+1 -( 2 * DATEDIFF( week, @StartDate, @EndDate ) ) + CASE WHEN DATENAME(dw, @StartDate) = 'Saturday' THEN 1 ELSE 0 END - CASE WHEN DATENAME(dw, @EndDate) = 'Saturday' THEN 1 ELSE 0 END SELECT @RAWDAYS - COUNT(*) FROM HOLIDAY NumberOfBusinessDays WHERE [Holiday_Date] BETWEEN @StartDate+1 AND @EndDate 

Usando uma tabela de datas:

  DECLARE @StartDate date = '2014-01-01', @EndDate date = '2014-01-31'; SELECT COUNT(*) As NumberOfWeekDays FROM dbo.Calendar WHERE CalendarDate BETWEEN @StartDate AND @EndDate AND IsWorkDay = 1; 

Se você não tem isso, você pode usar uma tabela de números:

  DECLARE @StartDate datetime = '2014-01-01', @EndDate datetime = '2014-01-31'; SELECT SUM(CASE WHEN DATEPART(dw, DATEADD(dd, Number-1, @StartDate)) BETWEEN 2 AND 6 THEN 1 ELSE 0 END) As NumberOfWeekDays FROM dbo.Numbers WHERE Number <= DATEDIFF(dd, @StartDate, @EndDate) + 1 -- Number table starts at 1, we want a 0 base 

Ambos devem ser rápidos e eliminar a ambiguidade / complexidade. A primeira opção é a melhor, mas se você não tiver uma tabela de calendars, você pode sempre criar uma tabela de números com um CTE.

Esta é basicamente a resposta do CMS sem a dependência de uma determinada configuração de idioma. E já que estamos filmando genérico, isso significa que ele deve funcionar para todas @@datefirst configurações @@datefirst também.

 datediff(day, , ) + 1 - datediff(week, , ) * 2 /* if start is a Sunday, adjust by -1 */ + case when datepart(weekday, ) = 8 - @@datefirst then -1 else 0 end /* if end is a Saturday, adjust by -1 */ + case when datepart(weekday, ) = (13 - @@datefirst) % 7 + 1 then -1 else 0 end 

datediff(week, ...) sempre usa um limite de sábado a domingo por semanas, de modo que a expressão é determinística e não precisa ser modificada (contanto que nossa definição de dias da semana seja consistentemente de segunda a sexta). varia de acordo com a @@datefirst configuração @@datefirst e os cálculos modificados lidam com essa correção com a pequena complicação de alguma aritmética modular.

Uma maneira mais limpa de lidar com o assunto de sábado / domingo é traduzir as datas antes de extrair um valor de dia da semana. Após a mudança, os valores estarão de acordo com uma numeração fixa (e provavelmente mais familiar) que começa com 1 no domingo e termina com 7 no sábado.

 datediff(day, , ) + 1 - datediff(week, , ) * 2 + case when datepart(weekday, dateadd(day, @@datefirst, )) = 1 then -1 else 0 end + case when datepart(weekday, dateadd(day, @@datefirst, )) = 7 then -1 else 0 end 

Eu acompanhei esta forma da solução pelo menos até 2002 e um artigo de Itzik Ben-Gan. ( https://technet.microsoft.com/en-us/library/aa175781(v=sql.80).aspx ) Embora fosse necessário um pequeno ajuste, uma vez que os tipos de date mais recentes não permitem a aritmética de datas, são idênticos.

EDIT: Eu adicionei de volta o +1 que de alguma forma tinha sido deixado de fora. Também é importante notar que esse método sempre conta os dias inicial e final. Ele também assume que a data final está em ou após a data de início.

 DECLARE @StartDate datetime,@EndDate datetime select @StartDate='3/2/2010', @EndDate='3/7/2010' DECLARE @TotalDays INT,@WorkDays INT DECLARE @ReducedDayswithEndDate INT DECLARE @WeekPart INT DECLARE @DatePart INT SET @TotalDays= DATEDIFF(day, @StartDate, @EndDate) +1 SELECT @ReducedDayswithEndDate = CASE DATENAME(weekday, @EndDate) WHEN 'Saturday' THEN 1 WHEN 'Sunday' THEN 2 ELSE 0 END SET @TotalDays=@TotalDays-@ReducedDayswithEndDate SET @WeekPart=@TotalDays/7; SET @DatePart=@TotalDays%7; SET @WorkDays=(@WeekPart*5)+@DatePart SELECT @WorkDays 
 CREATE FUNCTION x ( @StartDate DATETIME, @EndDate DATETIME ) RETURNS INT AS BEGIN DECLARE @Teller INT SET @StartDate = DATEADD(dd,1,@StartDate) SET @Teller = 0 IF DATEDIFF(dd,@StartDate,@EndDate) <= 0 BEGIN SET @Teller = 0 END ELSE BEGIN WHILE DATEDIFF(dd,@StartDate,@EndDate) >= 0 BEGIN IF DATEPART(dw,@StartDate) < 6 BEGIN SET @Teller = @Teller + 1 END SET @StartDate = DATEADD(dd,1,@StartDate) END END RETURN @Teller END 

Tomei os vários exemplos aqui, mas na minha situação particular, temos um @PromisedDate para entrega e um @ReceivedDate para o recebimento real do item. Quando um item foi recebido antes da “PromisedDate”, os cálculos não foram totalizados corretamente, a menos que eu ordenei que as datas fossem passadas para a function por ordem de calendar. Não querendo checar as datas toda vez, mudei a function para lidar com isso para mim.

 Create FUNCTION [dbo].[fnGetBusinessDays] ( @PromiseDate date, @ReceivedDate date ) RETURNS integer AS BEGIN DECLARE @days integer SELECT @days = Case when @PromiseDate > @ReceivedDate Then DATEDIFF(d,@PromiseDate,@ReceivedDate) + ABS(DATEDIFF(wk,@PromiseDate,@ReceivedDate)) * 2 + CASE WHEN DATENAME(dw, @PromiseDate) <> 'Saturday' AND DATENAME(dw, @ReceivedDate) = 'Saturday' THEN 1 WHEN DATENAME(dw, @PromiseDate) = 'Saturday' AND DATENAME(dw, @ReceivedDate) <> 'Saturday' THEN -1 ELSE 0 END + (Select COUNT(*) FROM CompanyHolidays WHERE HolidayDate BETWEEN @ReceivedDate AND @PromiseDate AND DATENAME(dw, HolidayDate) <> 'Saturday' AND DATENAME(dw, HolidayDate) <> 'Sunday') Else DATEDIFF(d,@PromiseDate,@ReceivedDate) - ABS(DATEDIFF(wk,@PromiseDate,@ReceivedDate)) * 2 - CASE WHEN DATENAME(dw, @PromiseDate) <> 'Saturday' AND DATENAME(dw, @ReceivedDate) = 'Saturday' THEN 1 WHEN DATENAME(dw, @PromiseDate) = 'Saturday' AND DATENAME(dw, @ReceivedDate) <> 'Saturday' THEN -1 ELSE 0 END - (Select COUNT(*) FROM CompanyHolidays WHERE HolidayDate BETWEEN @PromiseDate and @ReceivedDate AND DATENAME(dw, HolidayDate) <> 'Saturday' AND DATENAME(dw, HolidayDate) <> 'Sunday') End RETURN (@days) END 

Se você precisar adicionar dias úteis a uma determinada data, poderá criar uma function que depende de uma tabela de calendar, descrita abaixo:

 CREATE TABLE Calendar ( dt SMALLDATETIME PRIMARY KEY, IsWorkDay BIT ); --fill the rows with normal days, weekends and holidays. create function AddWorkingDays (@initialDate smalldatetime, @numberOfDays int) returns smalldatetime as begin declare @result smalldatetime set @result = ( select t.dt from ( select dt, ROW_NUMBER() over (order by dt) as daysAhead from calendar where dt > @initialDate and IsWorkDay = 1 ) t where t.daysAhead = @numberOfDays ) return @result end 

Isso está funcionando para mim, no meu país no sábado e domingo são dias não úteis.

Para mim é importante o tempo de @StartDate e @EndDate.

 CREATE FUNCTION [dbo].[fnGetCountWorkingBusinessDays] ( @StartDate as DATETIME, @EndDate as DATETIME ) RETURNS INT AS BEGIN DECLARE @res int SET @StartDate = CASE WHEN DATENAME(dw, @StartDate) = 'Saturday' THEN DATEADD(dd, 2, DATEDIFF(dd, 0, @StartDate)) WHEN DATENAME(dw, @StartDate) = 'Sunday' THEN DATEADD(dd, 1, DATEDIFF(dd, 0, @StartDate)) ELSE @StartDate END SET @EndDate = CASE WHEN DATENAME(dw, @EndDate) = 'Saturday' THEN DATEADD(dd, 0, DATEDIFF(dd, 0, @EndDate)) WHEN DATENAME(dw, @EndDate) = 'Sunday' THEN DATEADD(dd, -1, DATEDIFF(dd, 0, @EndDate)) ELSE @EndDate END SET @res = (DATEDIFF(hour, @StartDate, @EndDate) / 24) - (DATEDIFF(wk, @StartDate, @EndDate) * 2) SET @res = CASE WHEN @res < 0 THEN 0 ELSE @res END RETURN @res END GO 

Criar function como:

 CREATE FUNCTION dbo.fn_WorkDays(@StartDate DATETIME, @EndDate DATETIME= NULL ) RETURNS INT AS BEGIN DECLARE @Days int SET @Days = 0 IF @EndDate = NULL SET @EndDate = EOMONTH(@StartDate) --last date of the month WHILE DATEDIFF(dd,@StartDate,@EndDate) >= 0 BEGIN IF DATENAME(dw, @StartDate) <> 'Saturday' and DATENAME(dw, @StartDate) <> 'Sunday' and Not ((Day(@StartDate) = 1 And Month(@StartDate) = 1)) --New Year's Day. and Not ((Day(@StartDate) = 4 And Month(@StartDate) = 7)) --Independence Day. BEGIN SET @Days = @Days + 1 END SET @StartDate = DATEADD(dd,1,@StartDate) END RETURN @Days END 

Você pode chamar a function como:

 select dbo.fn_WorkDays('1/1/2016', '9/25/2016') 

Ou como:

 select dbo.fn_WorkDays(StartDate, EndDate) from table1 
 Create Function dbo.DateDiff_WeekDays ( @StartDate DateTime, @EndDate DateTime ) Returns Int As Begin Declare @Result Int = 0 While @StartDate <= @EndDate Begin If DateName(DW, @StartDate) not in ('Saturday','Sunday') Begin Set @Result = @Result +1 End Set @StartDate = DateAdd(Day, +1, @StartDate) End Return @Result 

Fim

Eu encontrei o abaixo TSQL uma solução bastante elegante (eu não tenho permissions para executar funções). Eu encontrei o DATEFIRST ignora DATEFIRST e eu queria que meu primeiro dia da semana fosse uma segunda-feira. Eu também queria que o primeiro dia de trabalho fosse definido como zero e se cair em um fim de semana, a segunda-feira será um zero. Isso pode ajudar alguém que tem um requisito um pouco diferente 🙂

Não lida com feriados

 SET DATEFIRST 1 SELECT ,(DATEDIFF(DD, [StartDate], [EndDate])) -(DATEDIFF(wk, [StartDate], [EndDate])) -(DATEDIFF(wk, DATEADD(dd,-@@DATEFIRST,[StartDate]), DATEADD(dd,-@@DATEFIRST,[EndDate]))) AS [WorkingDays] FROM /*Your Table*/ 

Uma abordagem é “percorrer as datas” do início ao fim em conjunto com uma expressão de caso que verifica se o dia não é um sábado ou um domingo e sinaliza (1 para o dia da semana, 0 para o final de semana). E no final apenas sum sinalizadores (seria igual à contagem de 1 sinalizadores como o outro sinalizador é 0) para fornecer o número de dias da semana.

Você pode usar um tipo de function de utilitário GetNums (startNumber, endNumber) que gera uma série de números para ‘looping’ desde a data de início até a data final. Consulte http://tsql.solidq.com/SourceCodes/GetNums.txt para uma implementação. A lógica também pode ser estendida para atender feriados (digamos que você tenha uma tabela de feriados)

 declare @date1 as datetime = '19900101' declare @date2 as datetime = '19900120' select sum(case when DATENAME(DW,currentDate) not in ('Saturday', 'Sunday') then 1 else 0 end) as noOfWorkDays from dbo.GetNums(0,DATEDIFF(day,@date1, @date2)-1) as Num cross apply (select DATEADD(day,n,@date1)) as Dates(currentDate) 

Como com DATEDIFF, não considero a data final como parte do intervalo. O número de (por exemplo) domingos entre @StartDate e @EndDate é o número de domingos entre uma segunda-feira “inicial” e a @EndDate menos o número de domingos entre esta segunda-feira “inicial” e a @StartDate. Sabendo disso, podemos calcular o número de dias úteis da seguinte forma:

 DECLARE @StartDate DATETIME DECLARE @EndDate DATETIME SET @StartDate = '2018/01/01' SET @EndDate = '2019/01/01' SELECT DATEDIFF(Day, @StartDate, @EndDate) -- Total Days - (DATEDIFF(Day, 0, @EndDate)/7 - DATEDIFF(Day, 0, @StartDate)/7) -- Sundays - (DATEDIFF(Day, -1, @EndDate)/7 - DATEDIFF(Day, -1, @StartDate)/7) -- Saturdays 

Cumprimentos!

Eu sei que esta é uma pergunta antiga, mas eu precisava de uma fórmula para dias úteis, excluindo a data de início, pois tenho vários itens e preciso dos dias para acumular corretamente.

Nenhuma das respostas não iterativas funcionou para mim.

Eu usei uma definição como

Número de vezes que meia-noite a segunda, terça, quarta, quinta e sexta-feira são passadas

(outros podem contar de meia-noite a sábado em vez de segunda-feira)

Acabei com essa fórmula

 SELECT DATEDIFF(day, @StartDate, @EndDate) /* all midnights passed */ - DATEDIFF(week, @StartDate, @EndDate) /* remove sunday midnights */ - DATEDIFF(week, DATEADD(day, 1, @StartDate), DATEADD(day, 1, @EndDate)) /* remove saturday midnights */