Junção com 3 tabelas no firebird
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?
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
Curtidas 0
Respostas
Chromusmaster
15/01/2024
No próprio site tem um artigo
https://www.devmedia.com.br/trabalhando-com-joins-no-firebird/33054
https://www.devmedia.com.br/trabalhando-com-joins-no-firebird/33054
GOSTEI 0
Arthur Heinrich
15/01/2024
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.
Depois, em cima deste resultado, você utiliza funções analíticas para retornar na linha, uma coluna da linha anterior.
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.
Feito isso, você terá registros do tipo (funcionario_id, entrada, saida). Podemos agora, relacionar este resultado com a tabela funcionarios, para retornar o nome:
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
GOSTEI 0