Consulta no MYSQL

10 respostas
leandrosu

Bom dia Pessoal,

Estou com certa dificuldade em relacionar duas tabelas no mysql.

O que acontece é o seguinte:

Tabela integracao_veiculos ( 257 registros )
- idVeiculo
- placa
- motorista

Tabela integracao_eventos ( 374329 registros, a cada 30 seg recebo em media + 100 registros )
- idVeiculo
- idMensagem
- latitude
- longitude

Querry que estou utilizando para mostrar os registros,

SELECT * FROM integracao_veiculos 
		INNER JOIN integracao_eventos ON (integracao_veiculos.idVeiculo = integracao_eventos.idVeiculo) ORDER BY integracao_veiculos.placa

Mas no caso eu preciso mostrar apenas o ultimo registro de cada veiculo ( hoje seriam 257 veiculos e nao os 374329 ).

Ja tentei utilizar o Group By mas mesmo assim demora muito ( ele continua percorrendo a tabela toda dos eventos antes de retornar os dados ).

De que forma eu posso fazer isso ?

Desde ja muito obrigado.

Abraco

10 Respostas

pmlm

Algo assim?

SELECT * FROM integracao_veiculos v  
            INNER JOIN integracao_eventos e ON v.idVeiculo = e.idVeiculo) 
 WHERE e.idMensagem = (SELECT max(e2.idMensagem) FROM integracao_eventos e2 WHERE e.idVeiculo = e2.idVeiculo)
 ORDER BY integracao_veiculos.placa
A

Eu acho que o seu problema está na modelagem do banco de dados. Como você sabe qual row da tabela integracao_eventos é o último registro referente a um veículo? Você deveria ter um campo tipo ind_vigente_integracao (boolean ou varchar para ´S´/´N’), onde somente a integração seria TRUE (ou ´S´) ou então um campo de data_disponibilizacao na tabela integracao_eventos. Assim , você poderia complementar a sua query da seguinte forma:

SELECT * FROM integracao_veiculos 
		INNER JOIN integracao_eventos ON (integracao_veiculos.idVeiculo = integracao_eventos.idVeiculo) 
WHERE IND_VIGENTE_INTEGRACAO = 'S'
ORDER BY integracao_veiculos.placa

Ou, para o caso de data:

SELECT * FROM integracao_veiculos 
		INNER JOIN integracao_eventos ON (integracao_veiculos.idVeiculo = integracao_eventos.idVeiculo) 
WHERE DATA_DISPONIBILIZACAO = (SELECT MAX(DATA_DISPONIBILIZACAO) FROM integracao_eventos
                                                        WHERE  integracao_eventos.idVeiculo = integracao_veiculos.idVeiculo)
ORDER BY integracao_veiculos.placa
leandrosu

pmlm:
Algo assim?

SELECT * FROM integracao_veiculos v INNER JOIN integracao_eventos e ON v.idVeiculo = e.idVeiculo) WHERE e.idMensagem = (SELECT max(e2.idMensagem) FROM integracao_eventos e2 WHERE e.idVeiculo = e2.idVeiculo) ORDER BY integracao_veiculos.placa

Valeu pela ajuda pmlm, mas nao rolou :S

alex1975:
Eu acho que o seu problema está na modelagem do banco de dados. Como você sabe qual row da tabela integracao_eventos é o último registro referente a um veículo? Você deveria ter um campo tipo ind_vigente_integracao (boolean ou varchar para ´S´/´N’), onde somente a integração seria TRUE (ou ´S´) ou então um campo de data_disponibilizacao na tabela integracao_eventos. Assim , você poderia complementar a sua query da seguinte forma:

SELECT * FROM integracao_veiculos 
		INNER JOIN integracao_eventos ON (integracao_veiculos.idVeiculo = integracao_eventos.idVeiculo) 
WHERE IND_VIGENTE_INTEGRACAO = 'S'
ORDER BY integracao_veiculos.placa

Ou, para o caso de data:

SELECT * FROM integracao_veiculos 
		INNER JOIN integracao_eventos ON (integracao_veiculos.idVeiculo = integracao_eventos.idVeiculo) 
WHERE DATA_DISPONIBILIZACAO = (SELECT MAX(DATA_DISPONIBILIZACAO) FROM integracao_eventos
                                                        WHERE  integracao_eventos.idVeiculo = integracao_veiculos.idVeiculo)
ORDER BY integracao_veiculos.placa

Alex1975,

Cara eu tenho um campo data na tabela eventos. ( tipo datetime )

No caso a querry ficaria assim certo ?

SELECT * FROM integracao_veiculos INNER JOIN integracao_eventos ON (integracao_veiculos.idVeiculo = integracao_eventos.idVeiculo) WHERE integracao_eventos.data = (SELECT MAX(integracao_eventos.data) FROM integracao_eventos WHERE integracao_eventos.idVeiculo = integracao_veiculos.idVeiculo) ORDER BY integracao_veiculos.placa

pmlm

Deu algum erro?

alex1975:

SELECT * FROM integracao_veiculos INNER JOIN integracao_eventos ON (integracao_veiculos.idVeiculo = integracao_eventos.idVeiculo) WHERE integracao_eventos.data = (SELECT MAX(integracao_eventos.data) FROM integracao_eventos WHERE integracao_eventos.idVeiculo = integracao_veiculos.idVeiculo) ORDER BY integracao_veiculos.placa


Sim. Se reparares essa query é igual à minha. Eu pressupos que o ultimo registo seria o que tivesse idMensagem maior. Aqui o último registo é o que tem a data maior.

leandrosu

pmlm:
leandrosu:

Valeu pela ajuda pmlm, mas nao rolou :S

Deu algum erro?

alex1975:

SELECT * FROM integracao_veiculos INNER JOIN integracao_eventos ON (integracao_veiculos.idVeiculo = integracao_eventos.idVeiculo) WHERE integracao_eventos.data = (SELECT MAX(integracao_eventos.data) FROM integracao_eventos WHERE integracao_eventos.idVeiculo = integracao_veiculos.idVeiculo) ORDER BY integracao_veiculos.placa


Sim. Se reparares essa query é igual à minha. Eu pressupos que o ultimo registo seria o que tivesse idMensagem maior. Aqui o último registo é o que tem a data maior.

Entao,

Executei a query pelo mysql-front mesmo e ele nao retorna nem erro e nenhum registro.

Segue um screen dos ultimos registros do banco

A

Experimenta usar a seguinte query:

SELECT * FROM integracao_veiculos v    
            INNER JOIN integracao_eventos e ON v.idVeiculo = e.idVeiculo)   
WHERE e.idMensagem = (SELECT max(e2.id) FROM integracao_eventos e2 WHERE e.idVeiculo = e2.idVeiculo)  
ORDER BY integracao_veiculos.placa

É quase igual a query do pmlm, mas usa o campo id do integracao_eventos, que é a pk. Talvez a data não tenha rolado devido ao formato ddmmyyy hh21mmss. No Oracle eu costumo truncar estas datas, mas vai vir várias. E se você utilizar o campo idMensagem também vai vir várias, pois se repete. Tomara que agora funcione.

pmlm

alex1975:
Experimenta usar a seguinte query:

Uma pequena correção:

SELECT * FROM integracao_veiculos v    
            INNER JOIN integracao_eventos e ON v.idVeiculo = e.idVeiculo)   
WHERE e.id= (SELECT max(e2.id) FROM integracao_eventos e2 WHERE e.idVeiculo = e2.idVeiculo)  
ORDER BY integracao_veiculos.placa
leandrosu

alex1975:
Experimenta usar a seguinte query:

SELECT * FROM integracao_veiculos v    
            INNER JOIN integracao_eventos e ON v.idVeiculo = e.idVeiculo)   
WHERE e.idMensagem = (SELECT max(e2.id) FROM integracao_eventos e2 WHERE e.idVeiculo = e2.idVeiculo)  
ORDER BY integracao_veiculos.placa

É quase igual a query do pmlm, mas usa o campo id do integracao_eventos, que é a pk. Talvez a data não tenha rolado devido ao formato ddmmyyy hh21mmss. No Oracle eu costumo truncar estas datas, mas vai vir várias. E se você utilizar o campo idMensagem também vai vir várias, pois se repete. Tomara que agora funcione.

Valeu Alex, mas continua na mesma ele nao retorna nada :S
O que sera que pode ser ?

pmlm:
alex1975:
Experimenta usar a seguinte query:

Uma pequena correção:

SELECT * FROM integracao_veiculos v    
            INNER JOIN integracao_eventos e ON v.idVeiculo = e.idVeiculo)   
WHERE e.id= (SELECT max(e2.id) FROM integracao_eventos e2 WHERE e.idVeiculo = e2.idVeiculo)  
ORDER BY integracao_veiculos.placa

pmlm, cara tb nao retorna nada.

Ja to ficando meio maluco aqui. Ou demora mais de 1 min pra retornar tudo ( ai vem coisa que nem precisa ) ou nao retorna nada =/

leandrosu

Deixei essa querry rodando:

Demorou 02:23 min pra retornar 195 registros.

De que forma eu poderia otimizar essa consulta ?

A

Para mim o melhor seria o campo de ind_vigente_integracao que eu mencionei anteriormente. O select max percorre todo o banco e faz comparação sobre qual é o maior. Se para a tabela integracao_eventos somente o último registro para determinado veículo tivesse status = ´S´ (ou true), a execução seria mais rápida.

Criado 9 de julho de 2012
Ultima resposta 9 de jul. de 2012
Respostas 10
Participantes 3