Jump to content
Renan Cabral

Distinct no MySQL

Recommended Posts

Caros,

Preciso de uma grande ajuda e não estou conseguindo avançar.

 

Tenho um banco de dados MySQL com 1 tabela que contem mais de 8.000.000 campos. Basicamente ela é assim (exemplo):

ID ID_Equipamento Valor1 Valor2
5000 10 fdas 341341
4999 9 fdas 15145
4998 8 fasfa 4351
4997 7 fdafd 415
4996 3 das 67467
4995 2 dasdasdas 7
4994 1 qgrgbsg 74
4993 9 bsgb 423527
4992 8 sgarhy 6
4991 6 bsbsgb 8461546
4990 5 rwrqrqrgaf 5
4989 4 fvafdv 87
4988 3 afvafg 85
4987 1 afvafg 85
4986 5 ag 634
4985 3 gfag 2
4984 2 fdaga 51
4983 9 gfaga 431
4982 8 gffga 245262653
4981 6 gfa 2

 

Onde ID é um auto incrementador na hora da inserção de um dado.

E ID_Equipamento é a referência de qual equipamento as informações são.

 

Estou precisando pegar os últimos valores (Valor1, Valor2) de cada ID_Equipamento (Todos os ID_Equipamentos - 1 a 10, mas somente o último cadastrado).

O último valor seria pelo último ID cadastrado daquele ID_Equipamento

Nesse caso seria:

ID ID_Equipamento Valor1 Valor2
5000 10 fdas 341341
4999 9 fdas 15145
4998 8 fasfa 4351
4997 7 fdafd 415
4996 3 das 67467
4995 2 dasdasdas 7
4994 1 qgrgbsg 74
       
4991 6 bsbsgb 8461546
4990 5 rwrqrqrgaf 5
4989 4 fvafdv

87

 

 

Já tentei utilizar o DISTINCT, porém ele só retorna uma coluna com o ID_Equipamento:

ID_Equipamento
10
9
8
7
3
2
1
6
5
4

 

 

Há alguma possibilidade de fazer o que eu quero fazer? Ou usando group by? ou MAX(ID)?

Depois que conseguir fazer no MySQL, irei passar pro PHP e assim o tempo não pode ser tão alto para a execução...

 

Grato!

Share this post


Link to post
Share on other sites

Sim é possível, seguem alguns meios de se fazer isso, sendo o primeiro preferível aos outros:

SELECT
  tabela.id,
  tabela.id_equipamento,
  tabela.valor1,
  tabela.valor2 
FROM
  tabela
INNER JOIN
  (SELECT
     MAX(id) AS id
   FROM
     tabela
   GROUP BY
     id_equipamento) AS ultimo_registro_por_equipamento
ON
  ultimo_registro_por_equipamento.id = tabela.id
ORDER BY
  tabela.id DESC
  
/*Também é possível alcançar o mesmo resultado com as seguintes consultas porem a menos que o banco consiga otimiza-las elas tendem a ter um desempenho inferior.*/

SELECT
  tabela.id,
  tabela.id_equipamento,
  tabela.valor1,
  tabela.valor2 
FROM
  tabela
WHERE
  id IN (SELECT
     MAX(id)
   FROM
     tabela
   GROUP BY
     id_equipamento)
ORDER BY
  tabela.id DESC
  
/*ou*/

SELECT
  t1.id,
  t1.id_equipamento,
  t1.valor1,
  t1.valor2 
FROM
  tabela AS t1
WHERE
  id = (SELECT
     MAX(t2.id)
   FROM
     tabela AS t2
   WHERE
     t2.id_equipamento = t1.id_equipamento)
ORDER BY
  t1.id DESC

O que elas fazem é consultar os maiores IDs da tabela por equipamento e depois buscar os dados com base neles, as consultas alternativas tendem a ser mais lentas pois a subquery será executada para cada registro no banco enquanto com o join ela será executada somente uma vez.

 

Você pode realizar testes em http://sqlfiddle.com/#!9/01f85c/11.

Share this post


Link to post
Share on other sites

Obrigado pela ajuda.

Mas suponho que pela quantidade de IDs (10 milhões) e pela quantidade de ID_Equipamento (300), ainda continua lento o sistema.

A primeira ideia nem consegui rodar, ficou carregando...

 

Obrigado mais uma vez...

Share this post


Link to post
Share on other sites

Se o Id e id_equipamento possuem índices então o problema está sendo cruzar os dados com o sub select, nesse caso você pode substitui-lo por uma view materializada, que nada mais é que uma tabela auxiliar que você ira alimentar antes da consulta e/ou via triggers sempre que houver alterações na tabela.

 

VIEW MATERIALIZADA

CREATE TABLE ultimos_lancamentos (
    id INTEGER PRIMARY KEY,
    id_equipamento INTEGER NOT NULL UNIQUE,
    FOREIGN KEY fk_ultimos_lancamentos_id (id) REFERENCES tabela(id) ON DELETE CASCADE,
    FOREIGN KEY fk_ultimos_lancamentos_id_equipamento (id_equipamento) REFERENCES equipamentos(id) ON DELETE CASCADE
);

E caso raramente vá consultá-la pode populá-la antes de cada consulta.

TRUNCATE ultimos_lancamentos;

INSERT INTO ultimos_lancamentos(id, id_equipamento)
    SELECT MAX(id), id_equipamento FROM tabela GROUP BY id_equipamento;

Se for consultá-la constantemente pode atualizá-la imediatamente criando um triggers ao inserir e atualizar(caso o id do equipamento possa ser alterado posteriormente) a chave estrangeira já cuida da remoção quando houver.

CREATE TRIGGER atualizar_ultimos_lancamentos_insert AFTER INSERT ON tabela
       FOR EACH ROW REPLACE ultimos_lancamentos(id, id_equipamento) VALUES(NEW.id, NEW.id_equipamento);

CREATE TRIGGER atualizar_ultimos_lancamentos_update AFTER UPDATE ON tabela
       FOR EACH ROW REPLACE ultimos_lancamentos(id, id_equipamento) VALUES(NEW.id, NEW.id_equipamento);

Independente do modo escolhido sua consulta ficaria assim:

SELECT
  tabela.id,
  tabela.id_equipamento,
  tabela.valor1,
  tabela.valor2 
FROM
  tabela
INNER JOIN
  ultimos_lancamentos
ON
  ultimos_lancamentos.id = tabela.id
ORDER BY
  tabela.id DESC

 

Share this post


Link to post
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Similar Content

    • By _FelipeOlvr
      Talvez seja simples, ou não. Não sei.
      Mas gostaria de um esclarecimento/luz de gente que já tem bagagem na área. Ficarei muito agradecido pela informação.
       
      Dei umas pesquisadas por ai, e fiz testes com as duas maneiras que achei ( até agora ):
       
      file_get_contents ( 'http://......' ) ;
      curl () ;
       
      Pergunta: 
       
      Existem outras maneiras de consumir API via PHP ? Quais ?
      Essas duas aí estão corretas?
    • By santans
      <?php if(isset($_post['name']) && !empty($_post['name'])){ $nome = addslashes($_post['name']); $email = addslashes($_post['email']); $mensagem = addslashes($_post['mesage']); $to = "gabriel@symmetrycorp.com.br"; $subjet = "Formulario - Contato SITE"; $body = "Nome: ".$nome. "\r\n". "E-mail: ".$email. "\r\n". "Mensagem: ".$mesage. "\n"; $header = "From: gabriel@symmetrycorp.com.br "."\r\n"."Replay-to:".$email."\r\n"."X=Mailer:php/".phpversion(); if(mail($to, $subject, $body, $header)){ echo("E-mail enviado com sucesso"); }else{ echo("O e-mail não pode ser enviado"); } } ?> Gostaria de ajudar para conferir esse código para envio de email, quero ter certeza que não há nenhum erro de escrita do código...
    • By Masant12
      Por favor, estou tendo dificuldades, alguém poderia me ajudar, gostaria de saber como posso fazer um sistema de reserva e se isso é possível, pois não encontrei nem um material sobre isso na internet.
    • By michael450
      Senhores, boa tarde.
       
      Estou com um probleminha... rss', preciso fazer a listagem de uma função da biblioteca "SPED-NFe"   na qual consulto quais as NFe que emitiram contra meu CNPJ, porém o ele executa toda a função e depois me trás o resultado, eu gostaria de trazer o resultado instantaneamente, como se fosse uma atualização segundo a segundo.
       
       
      Essas informações não são salvas em DB, é apenas para consulta.
      Se alguém puder ajudar serei muito grato,
       
      Abraço.
       
      Michael Douglas
    • By ricardonews
      olá pessoal, alguém ja teve dificuldade de logar no banco com um formulario de login feito pelo ajax quando a senha é criptografada?
      a minha está o sendo pelo md5 e quando deixo sem criptografia eu logo no banco.  Eu gostaria de logar com criptografia.
      vou deixar  a index e o arquivo que busca no banco de dados
      <!doctype html> <html> <?php require_once"config.php"; ?> <head> <title>Formulario de login</title> <style type="text/css"> html{ height:100%; background: linear-gradient(rgba(38, 128, 101, 0.9), rgba(52, 177, 140, 0.9)); } #div_login{ width:500px; margin:40px auto; position:relative; background-color: #ffffff; padding: 20px; border-radius: 5px; } #message{ width:100%; text-align:center; color:red; margin-bottom: 20px; } #div_login h1 { text-align: center; } #div_login input, #div_login textarea,#div_login a{ padding:10px; border:1px solid rgba(38, 128, 101, 0.9); border-radius:4px; -moz-border-radius:4px; -webkit-border-radius:4px; outline:none; box-sizing: border-box; width:100%; font:14px "Trebuchet MS", tahoma, arial; color:#090; margin-bottom:10px; } #div_login #but_submit,#div_login a { background-color: #27ae60; font-weight: bold; text-transform: uppercase; color: #ffffff; width: auto; margin: 0; padding: 10px 20px; } </style> <!--<link href="style.css" rel="stylesheet" type="text/css">--> <script src="jquery-3.2.1.min.js" type="text/javascript"></script> <script type="text/javascript"> $(document).ready(function(){ $("#but_submit").click(function(){ var username = $("#meu_nome").val().trim(); var password = $("#minha_senha").val().trim(); if( username != "" && password != "" ){ $.ajax({ url:'pesquisar.php', type:'post', data:{username:username,password:password}, success:function(response){ var msg = ""; if(response == 1){ window.location = "home.php"; }else{ msg = "email e senhas invalidos!"; } $("#message").html(msg); } }); } }); }); </script> </head> <body> <div class="container"> <div id="div_login"> <h1>Login</h1> <div id="message"></div> <div> <input type="text" class="textbox" id="meu_nome" name="meu_nome" placeholder="email" /> </div> <div> <input type="password" class="textbox" id="minha_senha" name="minha_senha" placeholder="senhas"/> </div> <div> <input type="button" value="logar" name="but_submit" id="but_submit" /> <a href="inicio.php"><strong>Cadastrar</strong></a> </div> </div> </div> </body> </html> agora vem oque busca os dados no banco e é justamente essa parte que eu não entendo oque acontece.
      <?php require_once "config.php"; // AQUI É O PESQUISAR PHP $uname = mysqli_real_escape_string($con,$_POST['username']); $password = mysqli_real_escape_string($con,$_POST['password']); if ($uname != "" && $password != ""){ $sql_query = "SELECT count(*) as cntUser FROM usuarios WHERE email='".$uname."' and password='".$password."'"; $result = mysqli_query($con,$sql_query); $row = mysqli_fetch_array($result); $count = $row['cntUser']; if($count > 0){ $_SESSION['uname'] = $uname; echo 1; }else{ echo 0; } } desde já fico agradeço 
×

Important Information

Ao usar o fórum, você concorda com nossos Terms of Use.