web-dev-qa-db-fra.com

Comment sélectionner une ligne de valeur maximale dans la table mysql

J'ai le tableau suivant

Structure du tableau:

CREATE TABLE IF NOT EXISTS `people` ( 
`name` varchar(10) NOT NULL, 
`age` smallint(5) unsigned NOT NULL, 
PRIMARY KEY (`name`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

Insérez quelques valeurs:

INSERT INTO `people` (`name`, `age`) VALUES 
('bob', 13), 
('john', 25), 
('steve', 8), 
('sue', 13); 

Requête exécutée:

SELECT MAX(  `age` ) ,  `name` FROM  `people` WHERE 1

Résultat attendu:

25, John

Résultat généré

25, bob

Nous pouvons y parvenir en utilisant cette requête

SELECT `age`,  `name` FROM  `people` ORDER BY age DESC LIMIT 1

Question 1: Qu'est-ce que j'ai fait ici et pourquoi cette fonction MAX ne renvoie pas les informations de ligne pertinentes?

Question 2: Laquelle est bonne à utiliser pour augmenter la fonction MAX de performance ou la clause ORDER BY?

17
Sundar

Question 1: Qu'est-ce que j'ai fait ici et pourquoi cette fonction MAX ne renvoie pas les informations de ligne pertinentes?

Vous devez lire la clause group by.

MySQL est beaucoup plus permissif qu'il ne devrait, ce qui introduit de la confusion dans le processus. Fondamentalement, toute colonne sans agrégat doit être incluse dans la clause group by. Mais le sucre syntaxique MySQL permet "d'oublier" les colonnes. Lorsque vous le faites, MySQL crache une valeur arbitraire de l'ensemble par lequel il se regroupe. Dans votre cas, la première ligne de l'ensemble est bob, elle renvoie donc cela.

Question 2: Laquelle est bonne à utiliser pour augmenter la fonction MAX de performance ou la clause ORDER BY?

Votre première déclaration (en utilisant max() sans group by) Est tout simplement incorrecte.

Si vous voulez l'un des utilisateurs les plus âgés, order by age desc limit 1 Est la bonne façon de procéder.

Si vous voulez tous les utilisateurs les plus âgés, vous avez besoin d'une sous-sélection:

SELECT p.* FROM people p WHERE p.age = (select max(subp.age) from people subp);
21
Denis de Bernardy

essaye ça

SELECT age, name FROM  `people` where age = (SELECT max(age) FROM  people)
11
Napster

Encore une autre solution sans utilisation de fonctions agrégées et de regroupements:

SELECT * FROM people ORDER BY age DESC LIMIT 1

8
ghost28147

Qu'est-ce que j'ai fait ici et pourquoi cette fonction MAX ne renvoie pas les informations de ligne pertinentes?

MAX renvoie la valeur correcte - mais l'autre colonne que vous sélectionnez vous donne juste une valeur "aléatoire".

La sélection de colonnes qui ne font pas partie du GROUPing (et je pense que GROUP BY implicite se fait ici puisque vous utilisez une fonction d'agrégation) est illégale dans SQL strict - MySQL ignore cependant cela (selon la configuration du serveur), et vous donne une valeur à partir d'un ligne "aléatoire" dans de tels cas.


Des approches alternatives sont décrites ici: Les lignes contenant le maximum par groupe d'une certaine colonne

3
CBroe

Il existe une alternative intéressante qui ne fonctionne que sur MySql!

SELECT `Name`, `Age` FROM 
(SELECT `Name`, `Age`, 1 AS `foo`
FROM `People`
ORDER BY `Age` DESC) AS `x`
GROUP BY `foo`

Cela fonctionne car MySql renvoie la première ligne, lorsqu'aucune fonction d'agrégation n'est appliquée sur une colonne donnée

Voici le lien: http://tominology.blogspot.com.br/2014/10/sql-row-with-max-value.html

0
Marco

MAX est un fonction d'agrégation . Cela signifie que MySQL regroupe tous les enregistrements et les traite comme s'ils en faisaient un dans le jeu de résultats. Étant donné que vous n'indiquez pas comment la colonne de nom doit être groupée, le résultat peut être inattendu. COMMANDER PAR est un moyen parfaitement fin pour obtenir le résultat souhaité. N'oubliez pas d'ajouter un index sur l'âge afin que les performances ne soient pas affectées à mesure que la table grandit.

0
Bugs

Question 1: Si vous voulez vraiment utiliser MAX (), vous pouvez essayer cette SELECT age, name FROM people WHERE age IN (SELECT MAX(age) FROM people);

Question 2: Je pense que cela dépend, pour ma suggestion à la question 1, vous effectuez la requête deux fois, mais dans le ORDER BY solution que vous avez fournie, la base de données a effectué une procédure de tri similaire.

0
lhrec_106