Calculando dias úteis com SQL Server

Calculando dias úteis com SQL Server

Neste artigo você vai aprender como calcular dias úteis utilizando o SQL Server.

O cálculo de dias úteis é muito importante e tem várias aplicações, como por exemplo o cálculo de prazos de entrega e de pagamentos.

Vamos considerar como dia útil uma data que seja entre segunda a sexta, e que não caia em algum feriado.

Para servir de referência, vamos primeiro criar uma tabela com os feriados nacionais de 2020.

CREATE TABLE [dbo].[feriados](

[id] [int] IDENTITY(1,1) NOT NULL,

[data] [date] NULL,

[descricao] [varchar](50) NULL,

 CONSTRAINT [PK_feriados] PRIMARY KEY CLUSTERED 

(

[id] ASC

)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

) ON [PRIMARY]

 

Depois de criar a tabela, vamos inserir os registros com os feriados de 2020.

 

INSERT INTO feriados (data, descricao) VALUES ('2020-01-01', 'Confraternização Universal')

INSERT INTO feriados (data, descricao) VALUES ('2020-04-10', 'Paixão de Cristo')

INSERT INTO feriados (data, descricao) VALUES ('2020-04-21', 'Tiradentes')

INSERT INTO feriados (data, descricao) VALUES ('2020-05-01', 'Dia Mundial do Trabalho')

INSERT INTO feriados (data, descricao) VALUES ('2020-09-07', 'Independência do Brasil')

INSERT INTO feriados (data, descricao) VALUES ('2020-10-12', 'Nossa Senhora Aparecida')

INSERT INTO feriados (data, descricao) VALUES ('2020-11-02', 'Finados')

INSERT INTO feriados (data, descricao) VALUES ('2020-11-15', 'Proclamação da República')

INSERT INTO feriados (data, descricao) VALUES ('2020-12-25', 'Natal')

 

Para conferir, basta fazer:

 

SELECT * from feriados

 

Com a nossa tabela criada, vamos criar uma funçao para facilitar a geração de datas com base numa quantidade de dias úteis a ser informada pelo usuário. Antes de criar a função,  vamos entrar em detalhes de como ela vai funcionar:

 

1 - A função vai receber dois parâmetros, a data inicial e a quantidade de dias úteis a ser calculada.

2 - Será feito um loop de acordo com a quantidade de dias solicitados

3 - A data inicial será incrementada em 1 dia antes e durante a execução do loop

4 - Para cada nova data, será verificado se a nova data está no intervalo de dia da semana válido, e se a data não está em nossa tabela de feriados

5 - Ao concluir o loop, será retornada a nova data.

 

Existem três pontos que vamos dar uma olhada antes de criar a função. O primeiro é: Como saber o dia da semana de acordo com a data?

Para isso, se utiliza a funçao DATEPART, ela recebe dois parâmetros, o tipo de retorno e a data a ser analisada. O tipo de retorno que será utilizado é o WEEKDAY.

select DATEPART(WEEKDAY, '2020-02-29')

O retorno desta data é 7 (sábado). O retorno vai ser um número de 1 a 7. Por padrão, a semana começa no domingo (1) e termina no sábado (7).

O outro ponto que vamos ver é como adicionar dias a uma data. Para isso, se utilizada a função DATEADD, ela recebe 3 parâmetros, o primeiro é a referência (dias, mês, ano, etc...), o segundo é um número que representa a quantidade que vai ser adicionada, e por último, a data.  Se você informar a data de hoje e quiser saber a data de amanhã,  basta fazer a seguinte consulta:

SELECT DATEADD(DAY, 1, GETDATE())

Por último, para fazer o loop de acordo com a quantidade de dias solicitados, será utilizada uma estrutura de repetição chamada "While", que vai executar certas instruções enquanto uma variável de referência for válida.

DECLARA @DIAS_UTEIS INT  = 30

DECLARE @CONTADOR INT  = 0

WHILE @CONTADOR < @DIAS_UTEIS 

    BEGIN 

//Instrucoes que vamos executar

    SET @CONTADOR += 1; //Incrementar o contador

    END 

No exemplo acima ele vai executar as instrucoes dentro do While enquanto a variável "contador" for menor que 30.

Agora vamos criar a nossa função. Ela vai chamar "adicionar_dias_uteis", e vai receber dois parâmetros, uma data e uma quantidade de dias úteis. Seu retorno vai ser uma data.

CREATE FUNCTION adicionar_dias_uteis (

  @DATA      DATE,

  @DIAS_UTEIS     INT   

) RETURNS DATE     

BEGIN         

 

       IF @DATA IS NULL

         BEGIN       

           SET @DATA = GETDATE();

         END

 

       DECLARE @DIAS  INT  = 0

       DECLARE @CONTADOR      INT  = 0

       DECLARE @NOVA_DATA DATE = DATEADD(DAY, 1, @DATA)                                         

 

       WHILE @CONTADOR < @DIAS_UTEIS 

        BEGIN 

          IF DATEPART(WEEKDAY, @NOVA_DATA) NOT IN (7,1) AND @NOVA_DATA NOT IN ( SELECT data FROM feriados ) 

            SET @CONTADOR += 1;

            SELECT @NOVA_DATA = DATEADD(DAY, 1, @NOVA_DATA), @DIAS += 1;

        END 

 

        RETURN DATEADD(DAY, @DIAS, @DATA);

  END 

GO

 

Chegou a hora de testar. Como exemplo, vamos calcular 90 dias úteis a partir de 10/03/2020.

SELECT dbo.adicionar_dias_uteis('2020-03-10', 90)

O resultado será

2020-07-16

 

 

Outros conteudos que podem ser de seu interesse

Como localizar e excluir registros duplicados com SQL
24/07/2022SQL

Como localizar e excluir registros duplicados com SQL

Aprenda como localizar e excluir registros duplicados com SQL

Saiba mais...
SQL vs Excel - tabelas dinâmicas e agrupamento de resultados
16/01/2022SQL

SQL vs Excel - tabelas dinâmicas e agrupamento de resultados

Compare as formas de agrupar resultados no Excel e no SQL

Saiba mais...

Conteúdo sobre banco de dados sem complicação!