Junção com 3 tabelas no firebird

15/01/2024

0

Olá a todos, sou um pricipiante no delphi eu queria uma ajuda de vocês: Estou elaborando um sistema de registro de ponto eletrônico e com isso
tenho 3 tabelas no firebird 2.5

tabela funcionarios
ID
NOME

Tabela Entrada
ID
Funcionario_id
data
hr_Entrada

Tabela Saida
ID
Funcionario_id
hr_saida

Queria um select que uni-se as três tabelas para que eu possa fazer um pesquisa no delphi pelo nome e
outra pesquisa (separadamente) com as datas, onde iria pesquisar a data inicial e uma data final.

Alguém poderia me ajudar?
Vinicius

Vinicius

Responder

Posts

03/05/2024

Chromusmaster

Responder

03/05/2024

Arthur Heinrich

Esse modelo é ruim para fazer o que você quer.

Você pode relacionar facilmente "funcionários-entradas" ou "funcionários-saídas", mas não pode relacionar facilmente "entradas-saídas".

O problema é que, como a única referência direta é o funcionário_id, ao relacionar estas tabelas você gera um plano cartesiano entre todas as entradas com todas as saídas.

Além disso, sistemas do mundo real falham e você pode ter entradas sem a saída correspondente e saídas sem a entrada correspondente.

Uma coisa que é possível de se fazer é unir as entradas e saídas em um único resultado (E, S, E, S, E, S, ...), pois é esperado que isso ocorra.

select 'E' movimento, funcionario_id, hr_entrada hora from entrada
union all
select 'S' movimento, funcionario_id, hr_saida hora from entrada


Depois, em cima deste resultado, você utiliza funções analíticas para retornar na linha, uma coluna da linha anterior.

select
  funcionario_id,
  lag(movimento) over (partition by funcionario_id order by hora) movimento_ant,
  lag(hora) over (partition by funcionario_id order by hora) hora_ant,
  movimento,
  hora
from
  ( select 'E' movimento, funcionario_id, hr_entrada hora from entrada
    union all
    select 'S' movimento, funcionario_id, hr_saida hora from entrada ) d


Agora, você tem em uma mesma linha. para cada funcionario_id, um par (movimento, hora) anterior e outro atual.
Faz sentido que você considere apenas os que o movimento anterior seja a entrada e o atual seja a saída.

select
  funcionario_id,
  hora_ant entrada,
  hora saida
from
  ( select
      funcionario_id,
      lag(movimento) over (partition by funcionario_id order by hora) movimento_ant,
      lag(hora) over (partition by funcionario_id order by hora) hora_ant,
      movimento,
      hora
    from
      ( select 'E' movimento, funcionario_id, hr_entrada hora from entrada
        union all
        select 'S' movimento, funcionario_id, hr_saida hora from entrada ) d ) d
where
  movimento_ant = 'E' and
  movimento = 'S'


Feito isso, você terá registros do tipo (funcionario_id, entrada, saida). Podemos agora, relacionar este resultado com a tabela funcionarios, para retornar o nome:

select
  d.funcionario_id,
  f.nome,
  d.hora_ant entrada,
  d.hora saida
from
  ( select
      funcionario_id,
      lag(movimento) over (partition by funcionario_id order by hora) movimento_ant,
      lag(hora) over (partition by funcionario_id order by hora) hora_ant,
      movimento,
      hora
    from
      ( select 'E' movimento, funcionario_id, hr_entrada hora from entrada
        union all
        select 'S' movimento, funcionario_id, hr_saida hora from entrada ) d ) d
      join funcionarios f
        on f.id = d.funcionario_id
where
  d.movimento_ant = 'E' and
  d.movimento = 'S'
order by f.nome, d.hora_ant

Responder

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar