web-dev-qa-db-fra.com

MySQL: n'est pas dans GROUP BY

Le site produit des résultats, mais avec SELECT COUNT et une requête SELECT avec GROUP BY ayant deux comptes de résultats différents. Ceci est probablement dû à l'erreur affichée dans phpmyadmin mais pas sur le site.

Les requêtes:

SELECT count(DISTINCT `name`) as `numrows` FROM `users` WHERE `verified` = '1'

SELECT `name`, `type`, `language`, `code` FROM `users` WHERE `verified` = '1' GROUP BY `name` ORDER BY `count` DESC LIMIT 0, 25

PhpMyAdmin fournit l'erreur suivante:

1055 - "main.users.type" n'est pas dans GROUP BY

Lors de la lecture de la documentation MySQL, je ne sais toujours pas ce que je dois corriger. Je n'arrive pas à comprendre cela.

18
James Cordeiro

Vous devez avoir un groupe complet par:

SELECT `name`, `type`, `language`, `code` 
FROM `users` 
WHERE `verified` = '1' 
GROUP BY `name`, `type`, `language`, `code` 
ORDER BY `count` DESC LIMIT 0, 25

SQL92 exige que toutes les colonnes (à l'exception des agrégats) de la clause select fassent partie de la clause group by. SQL99 desserre un peu cette restriction et indique que toutes les colonnes de la clause select doivent dépendre fonctionnellement de la clause group by. MySQL autorise par défaut les groupes partiels par et ceci peut produire des réponses non déterministes, exemple:

create table t (x int, y int);
insert into t (x,y) values (1,1),(1,2),(1,3);
select x,y from t group by x;
+------+------+
| x    | y    |
+------+------+
|    1 |    1 |
+------+------+

C'est à dire. un y aléatoire est sélectionné pour le groupe x. On peut empêcher ce comportement en définissant @@ sql_mode:

set @@sql_mode='ONLY_FULL_GROUP_BY';
select x,y from t group by x; 
ERROR 1055 (42000): 'test.t.y' isn't in GROUP BY
29
Lennart

La meilleure solution à ce problème consiste bien entendu à utiliser une expression GROUP BY complète.

Mais il existe une autre solution qui fonctionne autour du blocage ONLY_FULL_GROUP_BY de l'ancienne extension MySQL sur GROUP BY.

SELECT name, 
       ANY_VALUE(type) type,
       ANY_VALUE(language) language,
       ANY_VALUE(code) code 
  FROM users  
 WHERE verified = '1' 
 GROUP BY name 
 ORDER BY count DESC LIMIT 0, 25

ANY_VALUE() déclare explicitement ce qui était auparavant implicite dans les opérations GROUP BY incomplètes de MySQL: le serveur peut choisir la valeur à renvoyer.

7
O. Jones

La première chose à faire est de voir pourquoi c'est comme ça. Les versions antérieures nous permettaient un peu de négligence: alors que les valeurs de la colonne groupée sont complètement listées (une de chaque sans exception) dans le résultat, les valeurs de la ou des autres colonnes sélectionnées sont plus ou moins omises - mais le code peut 'ne veut pas dire lesquels de votre part:

- Hey, MYSQL, list the families of the street - but add a first name as well to every row.
- Okay sir, but shall I use the father's or the mother's or...? I'm a machine, give exact orders!

Maintenant que nous comprenons le pourquoi, nous pouvons décider si nous avons des préférences concernant les autres colonnes. Utilisation

MAX() AS
MIN() AS
etc, works with strings, too

ou si c'est vraiment la même chose, par exemple il n'y a pas de différence entre les valeurs non agrégées liées au groupe, utilisez

ANY_VALUE() AS

Dans tous les cas, vous indiquez à mysql que vous êtes conscient d'être "équivoque", mais vous ne voulez vraiment pas vous concentrer sur toutes les colonnes autres que celles que vous avez regroupées.

0
Szél Lajos

Une autre solution mentionnée à plusieurs reprises ci-dessus consiste à désactiver cet agaçant 'ONLY_FULL_GROUP_BY' par exemple. comme dans cet article: Désactiver ONLY_FULL_GROUP_BY

Je pense que cette solution est très utile si vous ne voulez pas refactoriser le projet entier pendant plusieurs heures. Et si vous ne vous souciez pas des valeurs imprévisibles des colonnes qui ne sont pas la liste des GROUP BY.

0
Juri Sinitson