@AlirezaSoori: Apesar do nome, idé apenas uma coluna em uma tabela. Não há garantia de que os valores na idcoluna tenham que ser exclusivos.
unutbu
1
@unutbu Supondo que idnão seja uma chave primária ou única :) Dado o nome, há uma chance razoável de que seja. Também é importante notar que, dependendo do DBMS que você está usando, a abordagem com a subseleção pode ser muito menos eficiente.
Michael Mior
3
@MichaelMior: idpode ser uma chave estrangeira; nesse caso, pode não ser única. Fiz alguns testes comparativos set profiling = 1; ...; show profilese parece que nossas soluções têm o mesmo desempenho usando o MySQL. Para meu próprio conhecimento, você sabe qual DBMS tem desempenho inferior para as sub-seleções?
unutbu
1
Poderia ser uma chave estrangeira, mas como eu disse, estou apenas adivinhando com base no nome que não é. O MySQL é historicamente conhecido por ter um desempenho ruim com as sub-seleções. Isso melhorou bastante nas versões mais recentes, portanto depende da versão que você está usando. No entanto, repensando, essa consulta específica pode estar OK. Embora a execução de uma consulta algumas vezes com criação de perfil não diga necessariamente muito sobre desempenho relativo.
Michael Mior
149
Você também pode fazer
SELECTrowFROMtableORDERBY id DESC LIMIT 1;
Isso classificará as linhas por seu ID em ordem decrescente e retornará a primeira linha. É o mesmo que retornar a linha com o ID máximo. Obviamente, isso pressupõe que idé único entre todas as linhas. Caso contrário, pode haver várias linhas com o valor máximo para ide você obterá apenas uma.
Para fazer especificamente o que o OP está pedindo, eu faria isso. Mas as outras respostas fornecem uma melhor educação sobre a estrutura SQL :)
MatBailie
@ Dem Como assim? Nenhuma explicação é dada em outra resposta? É claro que também sou culpado disso :(
Michael Mior 30/09
Apenas outras perguntas corrigem a sintaxe sem refatorar a lógica. Portanto, o OP aprende como declarar corretamente esse sql específico.
precisa saber é o seguinte
Ponto justo :) Embora, sem dúvida, outras respostas ainda estejam corrigindo a lógica.
Michael Mior 30/09
E o desempenho? Eu cheguei aqui com esse tipo de consulta já funcionando para mim, mas eu queria saber se esse é o caminho certo. ORDER BY não é uma operação O (n * log n)?
dhill
27
SELECT*FROMtableWHERE id =(SELECT MAX(id)FROMTABLE)
@ shA.t SELECT entry FROM table WHERE id = MAX(id)não funcionaria ?!
Oldboy
@ shA.t Além disso, o que estou tentando fazer é o seguinte: SELECT entry_time FROM users_unverified WHERE num_id = (SELECT MAX(num_id) FROM users_unverified WHERE account_email = :account_email)pelo qual eu só preciso da entry_timeentrada mais recente no banco de dados. Essa declaração é suficiente ou deveria ser:SELECT entry_time FROM users_unverified WHERE num_id = (SELECT MAX(num_id) FROM users_unverified) AND account_email = :account_email
Oldboy
Não há significado confiável para a entrada mais recente em um resultado da consulta, você precisa ter um campo para o tempo de inserção e assim por diante. Entre, faça sua pergunta separadamente, espero que você receba mais atenções -HTH;).
shA.t 26/03/18
17
Você não pode dar order byporque order byfaz uma "verificação completa" em uma tabela.
A seguinte consulta é melhor:
SELECT*FROMtableWHERE id =(SELECT MAX(id)FROMtable);
ORDER BYnão fará uma varredura completa se você assumir que essa idé a chave primária da tabela. (E, se não estiver, é um nome muito ruim.) Se não estiver, como você espera MAX(id)trabalhar sem uma verificação completa da tabela? Se não houver índice, todos os valores ainda deverão ser verificados para encontrar o máximo.
Michael Mior 4/15
@CakeLikeBoss bem, na verdade, tentei a consulta "order by" e sua tabela "SELECT * FROM WHERE id = (SELECT MAX (id) FROM tabela);" consulta sobre uma tabela de 114 linhas, enquanto esta consulta levou exatamente 0,0004 segundos de cada vez, enquanto a segunda consulta tirou de 0,0007 para 0,0010 segundos eu repeti isso várias vezes
Prabhjot
1
Pode-se sempre optar por funções analíticas, o que lhe dará mais controle
select tmp.row from ( select row, rank() over(partition by id order by id desc ) as rnk from table) tmp where tmp.rnk=1
Se você tiver problemas com a função rank (), dependendo do tipo de dados, poderá escolher entre row_number () ou dense_rank () também.
A palavra-chave TOP não funciona no MySQL. Esta consulta não funcionará.
Anirudha Gupta 03/07
@toddmo: MySQL! E o Sql-Server também não é útil para outras pessoas. Você quer dizer MS-SQL?
22817 Rovererlele
@raiserle, você pode me ajudar a encontrar onde eu comentei ou postei algo sobre esta questão? Não consigo ver meu nome anexado a esta pergunta em nenhum lugar.
Respostas:
Você pode usar uma subseleção:
Observe que, se o valor de
max(id)
não for exclusivo, várias linhas serão retornadas.Se você quiser apenas uma dessas linhas, use a resposta de @ MichaelMior,
fonte
id
é apenas uma coluna em uma tabela. Não há garantia de que os valores naid
coluna tenham que ser exclusivos.id
não seja uma chave primária ou única :) Dado o nome, há uma chance razoável de que seja. Também é importante notar que, dependendo do DBMS que você está usando, a abordagem com a subseleção pode ser muito menos eficiente.id
pode ser uma chave estrangeira; nesse caso, pode não ser única. Fiz alguns testes comparativosset profiling = 1; ...; show profiles
e parece que nossas soluções têm o mesmo desempenho usando o MySQL. Para meu próprio conhecimento, você sabe qual DBMS tem desempenho inferior para as sub-seleções?Você também pode fazer
Isso classificará as linhas por seu ID em ordem decrescente e retornará a primeira linha. É o mesmo que retornar a linha com o ID máximo. Obviamente, isso pressupõe que
id
é único entre todas as linhas. Caso contrário, pode haver várias linhas com o valor máximo paraid
e você obterá apenas uma.fonte
fonte
SELECT entry FROM table WHERE id = MAX(id)
não funcionaria ?!SELECT entry_time FROM users_unverified WHERE num_id = (SELECT MAX(num_id) FROM users_unverified WHERE account_email = :account_email)
pelo qual eu só preciso daentry_time
entrada mais recente no banco de dados. Essa declaração é suficiente ou deveria ser:SELECT entry_time FROM users_unverified WHERE num_id = (SELECT MAX(num_id) FROM users_unverified) AND account_email = :account_email
Você não pode dar
order by
porqueorder by
faz uma "verificação completa" em uma tabela.A seguinte consulta é melhor:
fonte
ORDER BY
não fará uma varredura completa se você assumir que essaid
é a chave primária da tabela. (E, se não estiver, é um nome muito ruim.) Se não estiver, como você esperaMAX(id)
trabalhar sem uma verificação completa da tabela? Se não houver índice, todos os valores ainda deverão ser verificados para encontrar o máximo.Pode-se sempre optar por funções analíticas, o que lhe dará mais controle
select tmp.row from ( select row, rank() over(partition by id order by id desc ) as rnk from table) tmp where tmp.rnk=1
Se você tiver problemas com a função rank (), dependendo do tipo de dados, poderá escolher entre row_number () ou dense_rank () também.
fonte
Tente com isso
fonte