none
Calculo com horas RRS feed

  • Pergunta

  • Pessoal boa tarde! Tudo bem?

    Estou enfrentando algumas dificuldades para fazer um cálculo de horas. Preciso fazer um cálculo de horas trabalhadas de por um funcionário por dia (Folha de ponto).

    O que acontece é que existem valores tem dias que dão certo e dias que não dão, além de possuir um agravante que seria o horario noturno.

    Porém como o exemplo abaixo.:

    vários dias e estão com os valores incorretos.

    Segue abaixo meu código.:

    select
    	codfun, datpon, convert(varchar, datpon, 103) as dia, entr01, said01, entr02, said02,
    	case
    		when convert(int, substring(said01, 1, 2)) > convert(int, substring(entr01, 1, 2))
    			then abs(sum(datediff(second, convert(time, said01), convert(time, entr01))) / 60 / 60)
    		else
    			abs(sum(datediff(second, convert(time, entr01), convert(time, '23:59'))) / 60 / 60) + 
    			abs(sum(datediff(second, convert(time, '00:01'), convert(time, said01))) / 60 / 60)
    	end + 
    	case
    		when convert(int, substring(said02, 1, 2)) > convert(int, substring(entr02, 1, 2))
    			then abs(sum(datediff(second, convert(time, entr02), convert(time, said02))) / 60 / 60)
    		else
    			abs(sum(datediff(second, convert(time, entr02), convert(time, '23:59'))) / 60 / 60) + 
    			abs(sum(datediff(second, convert(time, '00:01'), convert(time, said02))) / 60 / 60)
    	end as Horas, 
    	case
    		when convert(int, substring(said01, 1, 2)) > convert(int, substring(entr01, 1, 2))
    			then abs(sum(datediff(second, convert(time, said01), convert(time, entr01))) / 60 % 60)
    		else
    			abs(sum(datediff(second, convert(time, entr01), convert(time, '23:59'))) / 60 % 60) + 
    			abs(sum(datediff(second, convert(time, '00:01'), convert(time, said01))) / 60 % 60)
    	end + 
    	case
    		when convert(int, substring(said02, 1, 2)) > convert(int, substring(entr02, 1, 2))
    			then abs(sum(datediff(second, convert(time, entr02), convert(time, said02))) / 60 % 60)
    		else
    			abs(sum(datediff(second, convert(time, entr02), convert(time, '23:59'))) / 60 % 60) + 
    			abs(sum(datediff(second, convert(time, '00:01'), convert(time, said02))) / 60 % 60)
    	end as Minutos
    from
    	Arq255
    where codfun = 14
    	and datpon >= '20210201'
    group by codfun, datpon, entr01, said01, entr02, said02
    go

    Alguém poderia me ajudar com alguma sugestão.

    Meu muito obrigado desde já!

    sexta-feira, 26 de fevereiro de 2021 20:50

Todas as Respostas

  • Rafa_060990,

    Por acaso estes dias que tem valores incorretos, seriam dias em que a hora começou em um dia e terminou no outro?

    Veja se este exemplo te ajuda:

    CREATE TABLE RESP1
    (
    	ID INT,
    	DATA DATE,
    	HORA TIME
    )
    Go
    
    INSERT INTO [RESP1] ([ID],[DATA],[HORA]) VALUES(145,Getdate(),'08:01:00')
    INSERT INTO [RESP1] ([ID],[DATA],[HORA]) VALUES(145,Getdate(),'12:08:00')
    INSERT INTO [RESP1] ([ID],[DATA],[HORA]) VALUES(145,Getdate(),'13:16:00')
    INSERT INTO [RESP1] ([ID],[DATA],[HORA]) VALUES(145,Getdate(),'17:02:00')
    
    INSERT INTO [RESP1] ([ID],[DATA],[HORA]) VALUES(145,Getdate()+1,'08:00:00')
    INSERT INTO [RESP1] ([ID],[DATA],[HORA]) VALUES(145,Getdate()+1,'12:00:00')
    INSERT INTO [RESP1] ([ID],[DATA],[HORA]) VALUES(145,Getdate()+1,'13:00:00')
    INSERT INTO [RESP1] ([ID],[DATA],[HORA]) VALUES(145,Getdate()+1,'17:00:00')
    Go
    
    ;WITH LANCA AS (
    SELECT ID,DATA,HORA,
    ROW_NUMBER() OVER (
    PARTITION BY DATA,ID ORDER BY DATA,ID) AS POS
    FROM RESP1
    ),
    LANCAORG AS(
    SELECT  L1.ID,L1.DATA, L1.HORA AS ENTRADA, L2.HORA AS SAIDA
    FROM LANCA AS L1
    INNER JOIN LANCA AS L2 ON
    L1.ID = L2.ID AND L1.DATA = L2.DATA AND L1.POS = L2.POS - 1 AND L1.POS %2=1)
    
    SELECT ID, DATA,
        RIGHT('0' + CAST(SUM(DateDiff(Mi,Entrada,Saida)) / 60 As VARCHAR(2)),2) + ':' +
        RIGHT('0' + CAST(SUM(DateDiff(Mi,Entrada,Saida)) % 60 As VARCHAR(2)),2)
    As CargaHoraria
    FROM LANCAORG GROUP BY ID, Data
    Go



    Pedro Antonio Galvão Junior [MVP | MCC | MSTC | MIE | MTAC | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados Relacional e Data Warehouse | Professor Universitário | @JuniorGalvaoMVP | http://pedrogalvaojunior.wordpress.com]


    sexta-feira, 26 de fevereiro de 2021 23:08
  • Bom dia Junior! Tudo bem?

    Desde já meu muito obrigado pela resposta.

    Então, mudei meu código baseado no seu exemplo, e sim, deu certo quando o horário é diurno. Porém no noturno, quando tem a virada não dá certo o cálculo.

    Em minha base de dados, os valores não vem como um dia a frente, eles vem no mesmo dia, porém não bate os valores. Seguem resultados e o novo código.

    ;with cte_Diferencas as
    (
    select
    	codfun, datpon,
    	entr01, said01, entr02, said02,
    	entr03, said03, entr04, said04,
    
    	case
    		when convert(int, substring(said01, 1, 2)) > convert(int, substring(entr01, 1, 2))
    			then datediff(mi, convert(time, said01), convert(time, entr01))
    		else
    			datediff(mi, convert(time, entr01), convert(time, '23:59')) + 
    			datediff(mi, convert(time, '00:01'), convert(time, said01))
    	end as Dif1,
    
    	case
    		when convert(int, substring(said02, 1, 2)) > convert(int, substring(entr02, 1, 2))
    			then datediff(mi, convert(time, said02), convert(time, entr02))
    		else
    			datediff(mi, convert(time, entr02), convert(time, '23:59')) + 
    			datediff(mi, convert(time, '00:01'), convert(time, said02))
    	end as Dif2,
    
    	case
    		when convert(int, substring(said03, 1, 2)) > convert(int, substring(entr03, 1, 2))
    			then datediff(mi, convert(time, said03), convert(time, entr03))
    		else
    			datediff(mi, convert(time, entr03), convert(time, '23:59')) + 
    			datediff(mi, convert(time, '00:01'), convert(time, said03))
    	end as Dif3,
    
    	case
    		when convert(int, substring(said04, 1, 2)) > convert(int, substring(entr04, 1, 2))
    			then datediff(mi, convert(time, said04), convert(time, entr04))
    		else
    			datediff(mi, convert(time, entr04), convert(time, '23:59')) + 
    			datediff(mi, convert(time, '00:01'), convert(time, said04))
    	end as Dif4
    from
    	Arq255
    ),
    
    cte_Total as 
    (
    select
    	codfun, datpon, sum(Dif1 + Dif2 + Dif3 + Dif4) As TotalMinutos
    from
    	cte_Diferencas
    group by codfun, datpon
    )
    
    select
    	cte_Total.codfun, cte_Total.datpon,
    	Arq255.entr01, Arq255.said01, Arq255.entr02, Arq255.said02,
    	Arq255.entr03, Arq255.said03, Arq255.entr04, Arq255.said04,
        cast((TotalMinutos / 60) as varchar(2)) + ':' +
        cast((TotalMinutos % 60) as varchar(2)) As CargaHoraria
    from
    	cte_Total
    left outer join Arq255 on cte_Total.codfun = Arq255.codfun
    	and cte_Total.datpon = Arq255.datpon
    where cte_Total.codfun = 14
    	and cte_Total.datpon >= '20210201'
    go

    Alguma sugestão de como posso resolver?

    Obrigado!

    segunda-feira, 1 de março de 2021 11:27
  • rafa,

    Não estou entendendo o porquê você esta convertendo os dados?

    Qual é o tipo de dados que você esta utilizando para as colunas que vão armazenados os valores de datas?


    Pedro Antonio Galvão Junior [MVP | MCC | MSTC | MIE | MTAC | Microsoft Evangelist | Microsoft Partner | Engenheiro de Softwares | Especialista em Banco de Dados Relacional e Data Warehouse | Professor Universitário | @JuniorGalvaoMVP | http://pedrogalvaojunior.wordpress.com]

    segunda-feira, 1 de março de 2021 22:30