none
dias não úteis antes de uma data RRS feed

  • Pergunta

  • acho que a melhor forma para mostrar meu problema é dando de cara logo um exemplo:

    tenho a data 01/04/2013. eu preciso verificar quantos dias não úteis tem antes dessa data. nesse caso eu tenho 3. que são 31/03/2013, 30/03/2013 e 29/03/2013.

    ou seja, a data que for informada (como parametro, por exemplo), preciso verificar quantos dias não úteis tem antes dela.

    como posso fazer?
    segunda-feira, 1 de abril de 2013 17:08

Respostas

  • Rafa,

    Usei como base um thread aqui do fórum mesmo.

    http://social.msdn.microsoft.com/Forums/pt-BR/transactsqlpt/thread/95ed57e5-c9df-4dda-933f-16077b8534f5

    Veja este exemplo:
    DECLARE @DATA DATETIME = '2013-04-01'
    DECLARE @RANGE INT = -7
    
    DECLARE @RESULTADO TABLE
    (
      DIANAOUTIL DATETIME
    )
    
     DECLARE @DATAINICIO DATETIME = DATEADD(DAY,@RANGE,@DATA)
    
     WHILE @DATAINICIO <= @DATA
       BEGIN
        IF DATEPART(WEEKDAY, @DATAINICIO) IN (7,1) OR @DATAINICIO IN ( SELECT FERIADO FROM FERIADOS )  -- PARA OS FERIADOS TEM QUE TER UMA TABELA
    INSERT INTO @RESULTADO
    SELECT @DATAINICIO
    SELECT @DATAINICIO = DATEADD(DAY,1,@DATAINICIO)
       END
    
    SELECT * FROM @RESULTADO

    SQL Fiddle para ver em funcionamento:
    http://sqlfiddle.com/#!3/daddd/6

    Vitor Mendes | Seu feedback é muito importante para todos!
    Visite o meu site: http://www.vitormendes.com.br/

    • Marcado como Resposta rafa-martin segunda-feira, 1 de abril de 2013 18:02
    segunda-feira, 1 de abril de 2013 17:45
  • Rafa, fiz uma pequena alteração colocando mais um else no segundo case que vai funcionar, então no primeiro case, ele faz uma validação somente do dia da semana, se for domingo então ha 1 dia não util, segunda ha 2, terça nenhum e assim por diante, ja no segundo case ja é guardado o valor da variavel da quantidade de dias não uteis da semana que são fixos (sabado e domingo) e no segundo ele só valida na sua tabela de feriados 2 dias antes se ha algum registro, se tiver ele somente incrementa 1 ou 2 dias dependendo da sua tabela de feriados, veja se funciona agora:

    Declare @data datetime
    Declare @aux int
    set @data = '2013-03-25'
    set @aux = 0
    
    
    set @aux = (
    	case when DATEPART(WEEKDAY, @data) = 1 then 1 -- Domingo
    		 when DATEPART(WEEKDAY, @data) = 2 then 2 -- Segunda
    		 when DATEPART(WEEKDAY, @data) = 3 then 0 -- terca
    		 when DATEPART(WEEKDAY, @data) = 4 then 0 -- quarta
    		 when DATEPART(WEEKDAY, @data) = 5 then 0 -- quinta
    		 when DATEPART(WEEKDAY, @data) = 6 then 0 -- sexta
    		 when DATEPART(WEEKDAY, @data) = 7 then 0 -- Sabado
    	end)
    	
    select @aux
    
    set @aux = (
    	case when @aux = 0 and @data - 1 in (select feriado from #temp) then @aux + 1
    		 when @aux = 0 and @data - 1 in (select feriado from #temp) and @data - 2 in (select feriado from #temp) then @aux + 2
    		 when @aux = 1 and @data - 2 in (select feriado from #temp) then @aux + 1
    		 when @aux = 1 and @data - 2 in (select feriado from #temp) and @data - 3 in (select feriado from #temp) then @aux + 2
    		 when @aux = 2 and @data - 3 in (select feriado from #temp) then @aux + 1
    		 when @aux = 2 and @data - 3 in (select feriado from #temp) and @data - 4 in (select feriado from #temp) then @aux + 2
    		 Else @aux
    		end) 
    		
    select @aux


    Alexandre Matayosi Conde Mauricio.

    • Marcado como Resposta rafa-martin segunda-feira, 1 de abril de 2013 18:02
    segunda-feira, 1 de abril de 2013 17:59

Todas as Respostas

  • Rafa, primeiramente o que seriam dias não uteis ? sabado e domingo por exemplo seria facil de se fazer utilizando o datepart e pegando os dias anteriores validando se é sabado ou domingo, agora para feriados o sql não tem uma tabela de feriados, para isto acredito que voce tenha que ter uma tabela de cadastro destes dias para fazer esta validação.

    Alexandre Matayosi Conde Mauricio.

    segunda-feira, 1 de abril de 2013 17:25
  • os dias não úteis, seria sábado, domingo e feriado. 

    a tabela de feriados eu tenho. isso não é problema. 

    como posso fazer para identificar quantos dias não úteis tem antes de uma determinada data?

    segunda-feira, 1 de abril de 2013 17:27
  • Bom, pode não ser a maneira mais perfomatica que exista mas esta funcionando, nesse exemplo sua tabela de feriados seria a #temp e a data que voce quer verificar esta na @data o resultado vai sair na @aux, veja o exemplo que montei:

    create table #temp (Feriado datetime)
    
    insert into #temp
    values ('2013-03-29')
    
    Declare @data datetime
    Declare @aux int
    set @data = '2013-04-01'
    set @aux = 0
    
    
    set @aux = (
    	case when DATEPART(WEEKDAY, @data) = 1 then 1 -- Domingo
    		 when DATEPART(WEEKDAY, @data) = 2 then 2 -- Segunda
    		 when DATEPART(WEEKDAY, @data) = 3 then 0 -- terca
    		 when DATEPART(WEEKDAY, @data) = 4 then 0 -- quarta
    		 when DATEPART(WEEKDAY, @data) = 5 then 0 -- quinta
    		 when DATEPART(WEEKDAY, @data) = 6 then 0 -- sexta
    		 when DATEPART(WEEKDAY, @data) = 7 then 0 -- Sabado
    	end)
    
    
    set @aux = (
    	case when @aux = 0 and @data - 1 in (select feriado from #temp) then @aux + 1
    		 when @aux = 0 and @data - 1 in (select feriado from #temp) and @data - 2 in (select feriado from #temp) then @aux + 2
    		 when @aux = 1 and @data - 2 in (select feriado from #temp) then @aux + 1
    		 when @aux = 1 and @data - 2 in (select feriado from #temp) and @data - 3 in (select feriado from #temp) then @aux + 2
    		 when @aux = 2 and @data - 3 in (select feriado from #temp) then @aux + 1
    		 when @aux = 2 and @data - 3 in (select feriado from #temp) and @data - 4 in (select feriado from #temp) then @aux + 2
    		end)
    		
    select @aux
    	
    		 
    		 
    		 
    		 
    		 
    		 


    Alexandre Matayosi Conde Mauricio.

    segunda-feira, 1 de abril de 2013 17:41
  • Rafa,

    Usei como base um thread aqui do fórum mesmo.

    http://social.msdn.microsoft.com/Forums/pt-BR/transactsqlpt/thread/95ed57e5-c9df-4dda-933f-16077b8534f5

    Veja este exemplo:
    DECLARE @DATA DATETIME = '2013-04-01'
    DECLARE @RANGE INT = -7
    
    DECLARE @RESULTADO TABLE
    (
      DIANAOUTIL DATETIME
    )
    
     DECLARE @DATAINICIO DATETIME = DATEADD(DAY,@RANGE,@DATA)
    
     WHILE @DATAINICIO <= @DATA
       BEGIN
        IF DATEPART(WEEKDAY, @DATAINICIO) IN (7,1) OR @DATAINICIO IN ( SELECT FERIADO FROM FERIADOS )  -- PARA OS FERIADOS TEM QUE TER UMA TABELA
    INSERT INTO @RESULTADO
    SELECT @DATAINICIO
    SELECT @DATAINICIO = DATEADD(DAY,1,@DATAINICIO)
       END
    
    SELECT * FROM @RESULTADO

    SQL Fiddle para ver em funcionamento:
    http://sqlfiddle.com/#!3/daddd/6

    Vitor Mendes | Seu feedback é muito importante para todos!
    Visite o meu site: http://www.vitormendes.com.br/

    • Marcado como Resposta rafa-martin segunda-feira, 1 de abril de 2013 18:02
    segunda-feira, 1 de abril de 2013 17:45
  • alexandre,

    tem um detalhe: por exemplo dia 25/03/2013 é uma segunda - feira. então tenho 2 dias não úteis, seria domingo (24/03) e sábado (23/03). só que no segundo case está me trazendo o @aux null. no primeiro está correto. pq? não consegui entender porque no segundo case tem @data -2, -3, -1, etc...

    • Editado rafa-martin segunda-feira, 1 de abril de 2013 17:55 r
    segunda-feira, 1 de abril de 2013 17:51
  • Rafa, fiz uma pequena alteração colocando mais um else no segundo case que vai funcionar, então no primeiro case, ele faz uma validação somente do dia da semana, se for domingo então ha 1 dia não util, segunda ha 2, terça nenhum e assim por diante, ja no segundo case ja é guardado o valor da variavel da quantidade de dias não uteis da semana que são fixos (sabado e domingo) e no segundo ele só valida na sua tabela de feriados 2 dias antes se ha algum registro, se tiver ele somente incrementa 1 ou 2 dias dependendo da sua tabela de feriados, veja se funciona agora:

    Declare @data datetime
    Declare @aux int
    set @data = '2013-03-25'
    set @aux = 0
    
    
    set @aux = (
    	case when DATEPART(WEEKDAY, @data) = 1 then 1 -- Domingo
    		 when DATEPART(WEEKDAY, @data) = 2 then 2 -- Segunda
    		 when DATEPART(WEEKDAY, @data) = 3 then 0 -- terca
    		 when DATEPART(WEEKDAY, @data) = 4 then 0 -- quarta
    		 when DATEPART(WEEKDAY, @data) = 5 then 0 -- quinta
    		 when DATEPART(WEEKDAY, @data) = 6 then 0 -- sexta
    		 when DATEPART(WEEKDAY, @data) = 7 then 0 -- Sabado
    	end)
    	
    select @aux
    
    set @aux = (
    	case when @aux = 0 and @data - 1 in (select feriado from #temp) then @aux + 1
    		 when @aux = 0 and @data - 1 in (select feriado from #temp) and @data - 2 in (select feriado from #temp) then @aux + 2
    		 when @aux = 1 and @data - 2 in (select feriado from #temp) then @aux + 1
    		 when @aux = 1 and @data - 2 in (select feriado from #temp) and @data - 3 in (select feriado from #temp) then @aux + 2
    		 when @aux = 2 and @data - 3 in (select feriado from #temp) then @aux + 1
    		 when @aux = 2 and @data - 3 in (select feriado from #temp) and @data - 4 in (select feriado from #temp) then @aux + 2
    		 Else @aux
    		end) 
    		
    select @aux


    Alexandre Matayosi Conde Mauricio.

    • Marcado como Resposta rafa-martin segunda-feira, 1 de abril de 2013 18:02
    segunda-feira, 1 de abril de 2013 17:59
  • show de bola!!! dos dois scripts funcionaram perfeitamente. valeu!
    segunda-feira, 1 de abril de 2013 18:02