Comment sélectionner une ligne entière ayant le plus grand ID du tableau?

Réponses:

229

Vous pouvez utiliser une sous-sélection:

SELECT row 
FROM table 
WHERE id=(
    SELECT max(id) FROM table
    )

Notez que si la valeur de max(id)n'est pas unique, plusieurs lignes sont renvoyées.

Si vous ne voulez qu'une seule ligne, utilisez la réponse de @ MichaelMior,

SELECT row from table ORDER BY id DESC LIMIT 1
unutbu
la source
6
@AlirezaSoori: Malgré le nom, ce idn'est qu'une colonne dans un tableau. Il n'y a aucune garantie que les valeurs de la idcolonne doivent être uniques.
unutbu
1
@unutbu En supposant que ce idn'est pas une clé primaire ou unique :) Étant donné le nom, il y a une chance raisonnable que ce soit le cas. Il convient également de noter qu'en fonction du SGBD que vous utilisez, l'approche avec la sous-sélection peut être beaucoup moins efficace.
Michael Mior
3
@MichaelMior: idpeut être une clé étrangère, auquel cas elle peut ne pas être unique. J'ai fait des analyses comparatives en utilisant set profiling = 1; ...; show profileset il semble que nos solutions aient les mêmes performances avec MySQL. Pour ma propre connaissance, savez-vous quel SGBD a de moins bonnes performances pour les sous-sélections?
unutbu
1
Cela pourrait être une clé étrangère, mais comme je l'ai dit, je suppose simplement en fonction du nom que ce n'est pas le cas. MySQL est historiquement connu pour avoir de mauvaises performances avec les sous-sélections. Cela s'est considérablement amélioré dans les versions plus récentes, cela dépend donc de la version que vous utilisez. Cependant, en y repensant, cette requête particulière peut être OK. Bien que l'exécution d'une requête plusieurs fois avec le profilage n'en dise pas nécessairement beaucoup sur les performances relatives.
Michael Mior
150

Tu pourrais aussi faire

SELECT row FROM table ORDER BY id DESC LIMIT 1;

Cela triera les lignes par leur ID dans l'ordre décroissant et retournera la première ligne. Cela revient à renvoyer la ligne avec l'ID maximum. Cela suppose bien sûr qu'il idest unique parmi toutes les lignes. Sinon, il pourrait y avoir plusieurs lignes avec la valeur maximale pour idet vous n'en obtiendrez qu'une.

Michael Mior
la source
Pour faire précisément ce que le PO demande, je le ferais. Mais les autres réponses fournissent une meilleure éducation sur la structure SQL :)
MatBailie
@Dems Comment ça? Aucune explication n'est donnée sur une autre réponse? Bien sûr, je suis également coupable de cela :(
Michael Mior
Juste que d'autres questions corrigent la syntaxe sans refactoriser la logique. Ainsi, l'OP apprend à énoncer correctement ce SQL spécifique.
MatBailie
Bon point :) Bien que d'autres réponses corrigent sans doute encore la logique.
Michael Mior
Et les performances? Je suis arrivé ici avec ce genre de requête qui fonctionne déjà pour moi, mais je me demandais si c'était la bonne façon. ORDER BY n'est-il pas une opération O (n * log n)?
dhill
27
SELECT * 
FROM table 
WHERE id = (SELECT MAX(id) FROM TABLE)
Russell Shingleton
la source
@ shA.t SELECT entry FROM table WHERE id = MAX(id)ne fonctionnerait pas?!
oldboy
@ shA.t Aussi, ce que j'essaie de faire quelque chose comme ce qui suit: SELECT entry_time FROM users_unverified WHERE num_id = (SELECT MAX(num_id) FROM users_unverified WHERE account_email = :account_email)où j'ai juste besoin entry_timede l'entrée la plus récente dans la base de données. Cette déclaration est-elle suffisante ou devrait-elle l'être:SELECT entry_time FROM users_unverified WHERE num_id = (SELECT MAX(num_id) FROM users_unverified) AND account_email = :account_email
oldboy
Il n'y a pas de signification fiable pour l'entrée la plus récente dans un résultat de requête, vous devez avoir un champ pour l'heure d'insertion et ainsi de suite. BTW, veuillez poser votre question séparément, j'espère que vous obtiendrez plus d'attentions -HTH;).
jeu
17

Vous ne pouvez pas donner order bycar order byfait un "scan complet" sur une table.

La requête suivante est meilleure:

SELECT * FROM table WHERE id = (SELECT MAX(id) FROM table);
GâteauCommeBoss
la source
18
ORDER BYn'effectuera pas d'analyse complète si vous supposez qu'il ids'agit de la clé primaire de la table. (Et si ce n'est pas le cas, il est plutôt mal nommé.) Si ce n'est pas le cas, comment comptez-vous MAX(id)travailler sans une analyse complète de la table? S'il n'y a pas d'index, chaque valeur doit encore être vérifiée pour trouver le maximum.
Michael Mior
@CakeLikeBoss j'ai en fait essayé la requête "order by" et votre "SELECT * FROM table WHERE id = (SELECT MAX (id) FROM table);" requête sur une table de 114 lignes alors que cette requête prenait exactement 0,0004 sec à chaque fois tandis que la deuxième requête prenait de 0,0007 à 0,0010 sec Je l'ai répétée plusieurs fois
prabhjot
1

On peut toujours opter pour des fonctions analytiques qui vous donneront plus de contrôle

select tmp.row from ( select row, rank() over(partition by id order by id desc ) as rnk from table) tmp where tmp.rnk=1

Si vous rencontrez un problème avec la fonction rank () en fonction du type de données, vous pouvez également choisir entre row_number () ou dense_rank ().

Sumit Kumar
la source
0

Essayez avec ça

 SELECT top 1  id, Col2,  row_number() over (order by id desc)  FROM Table
Wella
la source
9
Le mot clé TOP ne fonctionne pas dans MySQL. Cette requête ne fonctionnera pas.
Anirudha Gupta
@toddmo: MySQL! Et Sql-Server n'est pas non plus utile pour les autres. Vous voulez dire MS-SQL?
raiserle
@raiserle, pouvez-vous m'aider à trouver où j'ai commenté ou posté quelque chose sur cette question? Je ne vois nulle part mon nom associé à cette question.
toddmo