Inquiridor
CURSOR NAO RETORNA TODOS OS DADOS

Pergunta
-
Boa tarde pessoal, tenho um cursor em cima de marcações de pontos (batidas) de funcionários, a ideia é somar o total de horas realizadas pelo funcionário no dia especificado, retirando a hora atual (ultima marcacao do funcionario) com a primeria marcação do mesmo, ou seja, trabalha com duas variaveis funcionairio. porém dentro da select ele está me retornando somente um registro (uma funcionaria) que se encontra no meio da tabela (o problema nao esta no inicio do cursor nem no final). Alguém pode dar uma olhada no codigo e ver se tem aalgum erro? Desde ja agradeço
DECLARE cursor_ponto SCROLL CURSOR
FOR select pe.PES_NOME as 'Nome', pe.PES_PIS as 'PIS', po.PON_DATAHORA as 'Data_Ponto', t.PJ_HRTOTAL - ((left(PJ_HRSINT1*100,1)+cast(right(PJ_HRSINT1*100,2)as float)/60) + (left(PJ_HRSINT2*100,1) +cast(right(PJ_HRSINT2*100,2)as float)/60) + (left(PJ_HRSINT3*100,1)+cast(right(PJ_HRSINT3*100,2)as float)/60)) as PJ_HRTOTAL
from [CONEX].[TELESSVR].[GAC_PONTO] po
inner join [CONEX].[TELESSVR].[GAC_PESSOA] pe on pe.PES_PIS = po.PON_PIS
inner join [MP11OFICIAL].[dbo].[SRA010] pp on CAST(pp.RA_PIS AS bigint) = po.PON_PIS
inner join [MP11OFICIAL].[dbo].[SM0010] fi on fi.M0_CODFIL = pp.RA_FILIAL
inner join [MP11OFICIAL].[dbo].[SPJ010] t on pp.RA_TNOTRAB = t.PJ_TURNO and t.PJ_DIA = DATEPART(dw,@data)
inner join CTT010 on CTT_CUSTO = RA_CC
where po.PON_TER_ID <> 8 /* desconsiderar os pontos de almoco */
and po.PON_DATAHORA between @data + ' 00:00:00' and @data + ' 23:59:59'
and RA_SITFOLH <> 'D' /* usuarios ativos */
and RA_REGRA = '01' /* para quem marca ponto */
and RA_CODFUNC not in ('00104') /* diferente de apresentador que nao marca ponto */
and M0_FILIAL COLLATE Latin1_General_CI_AS in (select * from dbo.split_string(rtrim(@filial),','))
and ltrim(rtrim(CTT_DESC01)) = ltrim(rtrim(@cc))
--and RA_TNOTRAB not in (83, 127)
--and pe.PES_NOME = rtrim(@nome)
--and pp.RA_CC = 24002 /* filtrar centro de custo do jornalismo */
OPEN cursor_ponto
DECLARE @atual_nome varchar (255)
DECLARE @antigo_nome varchar (255)
DECLARE @atual_pis varchar (12)
DECLARE @antigo_pis varchar (12)
DECLARE @atual_hora datetime
DECLARE @antigo_hora datetime
DECLARE @atual_jornada numeric
DECLARE @antigo_jornada numeric
DECLARE @total_horas numeric
DECLARE @status_ponto numeric
FETCH NEXT FROM cursor_ponto into @atual_nome, @atual_pis, @atual_hora, @atual_jornada
SET @status_ponto = 1
SET @total_horas = 0
INSERT INTO TMP_PONTO values (@atual_pis, @atual_nome,@total_horas,@status_ponto, @atual_jornada)
while @@Fetch_STATUS = 0
begin
SET @antigo_nome = @atual_nome
SET @antigo_pis = @atual_pis
SET @antigo_hora = @atual_hora
SET @antigo_jornada = @atual_jornada
FETCH NEXT FROM cursor_ponto into @atual_nome, @atual_pis, @atual_hora, @atual_jornada
if (@antigo_pis = @atual_pis) --and @atual_hora <> @antigo_hora)
begin
SET @status_ponto = @status_ponto + 1
if (@status_ponto%2=0)
begin
SET @total_horas = @total_horas + (datediff(ss,@atual_hora,@antigo_hora))
end
else
begin
SET @total_horas = @total_horas + datediff(ss,getdate(),@atual_hora)
end
UPDATE TMP_PONTO set trabalhado = @total_horas where pis = @atual_pis
UPDATE TMP_PONTO set status_ponto = @status_ponto where pis = @atual_pis
end
else
begin
if (@antigo_pis = @atual_pis and @atual_hora = @antigo_hora)
begin
SET @total_horas = @total_horas + (datediff(ss,@atual_hora,@antigo_hora))
UPDATE TMP_PONTO set trabalhado = @total_horas where pis = @atual_pis
UPDATE TMP_PONTO set status_ponto = @status_ponto where pis = @atual_pis
end
if (@antigo_pis <> @atual_pis)
begin
INSERT INTO TMP_PONTO values (@atual_pis, @atual_nome,0,1, @atual_jornada)
CONTINUE
end
end
end
CLOSE cursor_ponto
DEALLOCATE cursor_ponto
select distinct t.nome, t.jornada, CONVERT(varchar, DATEADD(ss, t.trabalhado, 0), 108) as trabalhado,
case when t.trabalhado>t.jornada*3600 then CONVERT(varchar, DATEADD(ss, (t.trabalhado-(t.jornada * 3600)), 0), 108)
when t.trabalhado<t.jornada*3600 then '- ' + CONVERT(varchar, DATEADD(ss, ((t.jornada * 3600) - t.trabalhado), 0), 108)
else '00:00:00' end as excedido, t.status_ponto
from TMP_PONTO t
inner join [MP11OFICIAL].[dbo].[SRA010] pe on case when isnumeric(pe.RA_PIS)=1 then cast(pe.RA_PIS as bigint) else 0 end = t.pis
where t.trabalhado>t.jornada*3600
order by excedido desc
END
GO
Todas as Respostas
-
-
Olá Daniel,
Não estou respondendo sobre o cursor. Porém, ao ver o seu problema, só queria propor uma forma diferente de atender seu objetivo.
Visto que cursores são pesados, em banco de dados, devemos sempre pensar no modo de programar em "set-based" ao invés de "row-based".
Proponho o seguinte código abaixo, como exemplo.
declare @TabelaPonto as table ( id int identity, idColaborador int, horaPonto datetime ) insert into @TabelaPonto values (1, getdate()-0.8), (1, getdate()-0.6), (1, getdate()-0.4), (1, getdate()-0.2), (2, getdate()-0.8), (2, getdate()-0.6), (2, getdate()-0.4) --Detalhado para entendimento ;with cte_ponto as ( select row_number() over (partition by idColaborador, convert(date, horaPonto) order by horaPonto asc) as sequenciaPontoColaborador, id, idColaborador, horaPonto, convert(date, horaPonto) as dia from @TabelaPonto as a ) select a.idColaborador, a.dia, a.horaPonto as 'Entrada', b.horaPonto as 'Saída' from ( select * from cte_ponto as a ) as a inner join ( select * from cte_ponto as b ) as b on a.idColaborador = b.idColaborador --Mesmo funcionário and a.dia = b.dia --Mesmo dia and a.sequenciaPontoColaborador + 1 = b.sequenciaPontoColaborador --O Ponto em Sequencia and a.sequenciaPontoColaborador%2 <> 0 --Calcular somente nas marcações não pares --Sumarizado ;with cte_ponto as ( select row_number() over (partition by idColaborador, convert(date, horaPonto) order by horaPonto asc) as sequenciaPontoColaborador, id, idColaborador, horaPonto, convert(date, horaPonto) as dia from @TabelaPonto as a ) select a.idColaborador, a.dia, sum(datediff(minute, a.horaPonto, b.horaPonto)) as totalMinutosDia from ( select * from cte_ponto as a ) as a inner join ( select * from cte_ponto as b ) as b on a.idColaborador = b.idColaborador --Mesmo funcionário and a.dia = b.dia --Mesmo dia and a.sequenciaPontoColaborador + 1 = b.sequenciaPontoColaborador --O Ponto em Sequencia and a.sequenciaPontoColaborador%2 <> 0 --Calcular somente nas marcações não pares group by a.idColaborador, a.dia
Jefferson [JeffSQL] Santos MCSE Data Management and Analytics jeffsql.com
- Sugerido como Resposta Junior Galvão - MVPMVP quinta-feira, 28 de setembro de 2017 00:36