Ruben Santos 0 Posted January 14, 2019 Report Share Posted January 14, 2019 Boa tarde, Sou novo no fórum e tambem em programação SQL, no entanto não desisto de procurar soluções e tentar aprender cada vez mais e melhor. Venho aqui pedir ajuda sobre o seguinte assunto: Estou trabalhando com Access e a tabela em questão apresenta as operações realizadas (tempo de trabalho) no caso de ter interrupção, a interrupção tem a durabilidade desde o fim da operação até ao inicio da proxima operação Então sobre esta tabela, faço a seguinte pesquisa para saber, quantas interrupções tenho e a que horas interromperam: Dei o nome de "Inicio_interrupcoes" SELECT dbo_opr.cod_gpt, dbo_opr.cod_pt, dbo_opr.un_pt, dbo_opr.data_ini, dbo_opr.data_fim, dbo_opr.cod_interrup, * FROM dbo_opr WHERE (((dbo_opr.cod_interrup) Is Not Null)); Este comando, executa corretamente, retornando todos os registos em que cod.interrup seja não nulo. Seguindo agora o código onde preciso milagrosamente de ajuda: SELECT inicio_interrupcoes.cod_gpt, inicio_interrupcoes.cod_pt, inicio_interrupcoes.un_pt, inicio_interrupcoes.data_fim, inicio_interrupcoes.cod_interrup FROM dbo_opr INNER JOIN inicio_interrupcoes ON (dbo_opr.cod_gpt = inicio_interrupcoes.cod_gpt) AND (dbo_opr.cod_pt = inicio_interrupcoes.cod_pt) GROUP BY inicio_interrupcoes.cod_gpt, inicio_interrupcoes.cod_pt, inicio_interrupcoes.un_pt, inicio_interrupcoes.data_fim, inicio_interrupcoes.cod_interrup, dbo_opr.data_ini HAVING (((dbo_opr.data_ini)>[inicio_interrupcoes].[data_fim])); Passando agora a explicar o que preciso: Na primeira consulta "Inicio_Interrupcoes" pesquiso todas os registos que contenham o campo "cod_interrup" preenchido. Na segunda consulta respeitando os campos "cod_gpt" e "cod_pt", pretendo obter a data de inicio da proxima operação que nesta consulta representa o fim da interrupção. Segue exemplo básico: considerem linha 2 e linha 3 da imagem: Linha 2 representa produção -> Inicio = 10/01/2019 08:21:13 Fim = 10/01/2019 12:54:30 Como o registo tem "Cod_interrup" considero que "10/01/2019 12:54:30" representa o inicio da interrupcão e o proximo inicio neste caso "10/01/2019 14:04:53" será o fim da interrupção e inicio da Produção. Alguem me pode dar uma força neste assunto? Obrigado, ficarei muito grato. Link to post Share on other sites
Ruben Santos 0 Posted January 14, 2019 Author Report Share Posted January 14, 2019 Alguem para ajudar? alguma luz? Link to post Share on other sites
Ruben Santos 0 Posted January 15, 2019 Author Report Share Posted January 15, 2019 Precisava mesmo de ajuda neste tópico, estou com imensas dificuldades e sem nenhuma luz. Link to post Share on other sites
Ricardo Voigt 8 Posted January 15, 2019 Report Share Posted January 15, 2019 Olá, primeira dúvida, neste teu caso, pode haver mais de uma interrupção? ou no máximo uma interrupção ? Minha primeira sugestão seria criar uma coluna "chave primária" numerada e sequencial. Assim, eu também tentaria transformar a coluna "cod_interrup" em uma "chave estrangeira", cujo valor apontaria para a "próxima linha lógica" da mesma tabela... Algo assim: cod data_ini data_fim cod_interrup 1 09/01/2019 15:48 09/01/2019 16:41 null 2 10/01/2019 08:21 10/01/2019 12:54 3 3 10/01/2019 14:04 10/01/2019 16:48 null 4 11/01/2019 08:12 11/01/2019 12:52 5 5 11/01/2019 14:14 11/01/2019 16:50 null 6 14/01/2019 08:43 14/01/2019 12:57 7 7 14/01/2019 14:04 null null Quanto ao comando select que busca os dados (não tenho certeza quanto ao Access pois não utilizo) acho que seria necessário fazer "left join" para buscar a provável "data_ini"... O comando select ficaria mais ou menos assim... select a_ini.data_ini, a_fim.data_ini, a_fim.data_fim from dbo_opr a_fim left join dbo_opr a_ini on (a_ini.cod_interrup = a_fim.cod) where a_fim.data_fim is not null and a_fim.cod_interrup is null Assim: existe a certeza de quando uma tarefa termina (a_fim) com a condição "a_fim.cod_interrup is null"; e se a condição "a_ini.data_ini is null" significa que NÃO houve interrupção. E abaixo, o resultado que eu obtive aqui testando/simulando no MYSQL: a_ini.data_ini a_fim.data_ini a_fim.data_fim NULL 09/01/2019 15:48 09/01/2019 16:41 10/01/2019 08:21 10/01/2019 14:04 10/01/2019 16:48 11/01/2019 08:12 11/01/2019 14:14 11/01/2019 16:50 Espero ter ajudado... Atenciosamente, Ricardo Link to post Share on other sites
Cerzedelo 41 Posted January 15, 2019 Report Share Posted January 15, 2019 Em primeiro lugar, o concelho que dou, é em vez de criar uma query tao complexa, ir fazendo por partes. Em segundo, não percebi, o porque de um inner join, quando só está a fazer select a campos de uma tabela. Em terceiro, o Access tinha uma ferramenta gráfica para fazer as querys, e depois apresentava os comandos em sql. O que provavelmente precisará e de fazer uma subquery, i. e., um select dentro de outro select.. Ver http://www.criarweb.com/artigos/subconsultas-em-sql.html Link to post Share on other sites
Ruben Santos 0 Posted January 15, 2019 Author Report Share Posted January 15, 2019 Boa tarde Ricardo Voigt e Cerzedelo, Obrigado pelas respostas, em primeiro lugar agradeço imenso ao Ricardo pelo exemplo, infelizmente não é o que procuro. E respondendo ás questões: Sim, terá várias interrupções. Agradeço também ao Cerzedelo, também pela resposta, esta penso aproximar-se bastante do que preciso. Passando a explicar: Considerem a seguinte tabela: Tabela "dbo_opr" Ver Melhor Considerem que esta tabela é os registos de produção. Se olharem para a linha 2 sei que a produção é desde "10/01/2019 08:21:13" até "10/01/2019 12:54:30" ao finalizar colocou "Cod_Interrup" E sei que a próxima produção começou em "10/01/2019 14:04:53" independentemente do final desta próxima operação, já consigo saber quanto tempo durou a minha interrupção. Preciso de obter o tempo de interrupção da seguinte maneira: Data_fim (registo 2) - Data_Ini (registo 3) Não preciso de obter o resultado para já, apenas de listar as datas. Tenho uma consulta que me retorna os registos que tenham "Cod_Interrup" SELECT dbo_opr.cod_gpt, dbo_opr.cod_pt, dbo_opr.un_pt, dbo_opr.data_ini, dbo_opr.data_fim, dbo_opr.cod_interrup FROM dbo_opr WHERE (((dbo_opr.cod_interrup) Is Not Null)); Após esta consulta tenho todos os registos que contenham "Cod_Interrup" guardada na consulta "Inicio_Interrup" O resultado será mais ou menos isto: Ver Melhor Faltando agora a segunda consulta em que tenho imensas dificuldades pelo seguinte: Pretendo fazer uma consulta á mesma tabela para me retornar o campo "Data_Ini" Neste caso a consulta tem as seguintes condições: dbo_opr.cod_gpt = inicio_Interrup.cod_gpt dbo_opr.cod_pt = inicio_Interrup.cod_pt e será a primeira "Data_Ini" > "Data_fim" Se considerarmos a tabela Inicial o resultado para a consulta que pretendo será o seguinte: Data_Fim = "10/01/2019 12:54:30" (linha2) <- Na minha consulta representa o inicio da interrupção porque tem o código "Cod_Interrup" Data_Ini = "10/01/2019 14:04:53" (linha3) <- Na minha consulta representa o fim da interrupção porque voltou a entrar em funcionamento. Ver Melhor Penso que a solução mais próxima do que preciso, será uma subconsulta, porém não estou a conseguir fazer. Agradeço desde já a ajuda e disponibilidade de todos Link to post Share on other sites
Ruben Santos 0 Posted January 15, 2019 Author Report Share Posted January 15, 2019 Boa tarde, Quase que já consegui obter o resultado que pretendo, contudo falta apenas limitar os resultados: SELECT DISTINCTROW dbo_opr.num_ordem, dbo_opr.num_operario, dbo_opr.cod_gpt, dbo_opr.cod_pt, dbo_opr.un_pt, dbo_opr.data_fim, dbo_opr.cod_interrup, dbo_opr_1.data_ini FROM dbo_opr LEFT JOIN dbo_opr AS dbo_opr_1 ON (dbo_opr.num_ordem = dbo_opr_1.num_ordem) AND (dbo_opr.num_oper = dbo_opr_1.num_oper) AND (dbo_opr.cod_pt = dbo_opr_1.cod_pt) AND (dbo_opr.cod_gpt = dbo_opr_1.cod_gpt) GROUP BY dbo_opr.num_ordem, dbo_opr.num_operario, dbo_opr.cod_gpt, dbo_opr.cod_pt, dbo_opr.un_pt, dbo_opr.data_fim, dbo_opr.cod_interrup, dbo_opr_1.data_ini HAVING (((dbo_opr.cod_interrup) Is Not Null) AND ((dbo_opr_1.data_ini)>[dbo_opr].[data_fim])) ORDER BY dbo_opr.data_fim; O resultado é o seguinte: Ver Melhor Preciso agora de ajuda para limitar o campo "Data_ini" a apenas 1 resultado superior a "Data_fim" Está a retornar todos os registos correspondentes, contudo preciso que me retorne apenas o primeiro. Obrigado, Rúben Santos Link to post Share on other sites
Joaanaa.93 1 Posted January 15, 2019 Report Share Posted January 15, 2019 (edited) Exprimenta assim: Select Top 1 From (SELECT DISTINCTROW dbo_opr.num_ordem, dbo_opr.num_operario, dbo_opr.cod_gpt, dbo_opr.cod_pt, dbo_opr.un_pt, dbo_opr.data_fim, dbo_opr.cod_interrup, dbo_opr_1.data_ini FROM dbo_opr LEFT JOIN dbo_opr AS dbo_opr_1 ON (dbo_opr.num_ordem = dbo_opr_1.num_ordem) AND (dbo_opr.num_oper = dbo_opr_1.num_oper) AND (dbo_opr.cod_pt = dbo_opr_1.cod_pt) AND (dbo_opr.cod_gpt = dbo_opr_1.cod_gpt) GROUP BY dbo_opr.num_ordem, dbo_opr.num_operario, dbo_opr.cod_gpt, dbo_opr.cod_pt, dbo_opr.un_pt, dbo_opr.data_fim, dbo_opr.cod_interrup, dbo_opr_1.data_ini HAVING (((dbo_opr.cod_interrup) Is Not Null) AND ((dbo_opr_1.data_ini)>[dbo_opr].[data_fim])) ORDER BY dbo_opr.data_fim) Where Data_ini > Data:fim; Edited January 15, 2019 by Joaanaa.93 Link to post Share on other sites
Ruben Santos 0 Posted January 15, 2019 Author Report Share Posted January 15, 2019 Boa Tarde Joana, Já testei e dá erro na execução do primeiro Select, mesmo assim penso que isso limitaria toda a consulta ao primeiro registo, ou seja apresentaria apenas o primeiro registo de toda a consulta, preciso limitar os dados que seleciono da tabela ALIAS "dbo_opr_1". Obrigado pela tentativa de ajuda Link to post Share on other sites
Ruben Santos 0 Posted January 15, 2019 Author Report Share Posted January 15, 2019 Será que a solução passa por converter o meu código em 1 select + (select limit 1)? Ou seja Um select limit 1 dentro de outro select? Será que alguem me pode ajudar a converter? Link to post Share on other sites
Joaanaa.93 1 Posted January 16, 2019 Report Share Posted January 16, 2019 (edited) 16 horas atrás, Ruben Santos disse: Boa Tarde Joana, Já testei e dá erro na execução do primeiro Select, mesmo assim penso que isso limitaria toda a consulta ao primeiro registo, ou seja apresentaria apenas o primeiro registo de toda a consulta, preciso limitar os dados que seleciono da tabela ALIAS "dbo_opr_1". Obrigado pela tentativa de ajuda Mas o limite não é quando a data de inicio é superior a data de fim? Eu não testei, mete o erro aqui Edited January 16, 2019 by Joaanaa.93 Link to post Share on other sites
Ruben Santos 0 Posted January 16, 2019 Author Report Share Posted January 16, 2019 Boas, Sim, já consegui resolver com a criação de um ALIAS, ficou mais ou menos assim: Inicio_Interrupcoes -> Busca todas as operações que contenham "cod_interrup" SELECT dbo_opr.tipo_ordem, dbo_opr.num_ordem, dbo_opr.num_oper, dbo_opr.num_operario, dbo_opr.cod_gpt, dbo_opr.cod_pt, dbo_opr.un_pt, dbo_opr.data_fim, dbo_opr.cod_interrup FROM dbo_opr WHERE (((dbo_opr.cod_interrup) Is Not Null)); Interrupcoes SELECT inicio_interrupcoes.tipo_ordem, inicio_interrupcoes.num_ordem, inicio_interrupcoes.num_oper, inicio_interrupcoes.num_operario, inicio_interrupcoes.cod_gpt, inicio_interrupcoes.cod_pt, inicio_interrupcoes.un_pt, inicio_interrupcoes.data_fim, inicio_interrupcoes.cod_interrup, (SELECT top 1 operacoes.data_ini FROM dbo_opr as operacoes WHERE (operacoes.cod_gpt=inicio_interrupcoes.cod_gpt) AND (operacoes.cod_pt=inicio_interrupcoes.cod_pt) AND (operacoes.un_pt=inicio_interrupcoes.un_pt) AND (operacoes.data_ini > inicio_interrupcoes.data_fim);) AS data_ini FROM inicio_interrupcoes ORDER BY inicio_interrupcoes.data_fim; Isto faz o restante código que busca a primeira data_ini que seja superior á data_fim. Obrigado pela ajuda de todos. Podem marcar o tópico como resolvido, no entanto podem deixar a solução para que possa audar outras pessoas com a mesma dificuldade. Link to post Share on other sites
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now