Avant MySQL 5.7, la valeur par défaut était d'autoriser non FULL group by
. Ce qui signifie que vous pouvez avoir un groupe par (qui utilise des fonctions d'agrégation comme sum
et max
et count
et group_concat
) avec d'autres colonnes non agrégées (appelons-les NON AGGS
) comme vos 3 premiers montrés pas tous partie de votre group by
clause. Cela l'a permis, mais les résultats se présentent généralement comme suit :
-
Cela a très bien fonctionné car vous connaissez bien vos données et essayez d'obtenir un
-
Ça s'est mal passé parce que c'était un bordel
Avant la version 5.7, ONLY_FULL_GROUP_BY
existait mais il était désactivé par défaut.
Donc, dans MySQL 5.7, vient le ONLY_FULL_GROUP_BY
activé par défaut. En tant que tel, si vous essayez un groupe par, mais avec pas tous le NON AGGS
dans le group by
clause, vous obtiendrez une erreur.
Considérez le problème suivant dans 5.6 ci-dessous :
create table thing
( col1 int not null,
col2 int not null,
age int not null
);
insert thing(col1,col2,age) values
(1,2,10),
(1,3,20),
(2,3,20),
(2,2,10);
select col1,col2,max(age) from thing group by col1;
+------+------+----------+
| col1 | col2 | max(age) |
+------+------+----------+
| 1 | 2 | 20 |
| 2 | 3 | 20 |
+------+------+----------+
Ce qui se passe ci-dessus n'est pas tout le NON AGGS
sont dans le group by
. Il renvoie le max(âge) par col1. Mais depuis col2
n'était pas dans le group by
, il a utilisé l'index de cluster ou l'ordre physique et lui a apporté, par inadvertance peut-être (un snafu, une erreur), la mauvaise valeur pour col2. Selon vos intentions ou connaissant vos données ou même bienveillant. Le moteur s'en fichait; peut-être que vous le faites.
Pour éviter ces erreurs courantes ou le retour de données par inadvertance, MySQL 5.7 active ONLY_FULL_GROUP_BY
par défaut.
Dans votre cas, les mauvaises lignes constituent probablement vos résultats pour les colonnes 2 et 3.
Voir la page de manuel intitulée Gestion MySQL de GROUP BY .
Exemple 2
-- drop table if exists person;
create table person
( id int auto_increment primary key,
firstName varchar(100) not null,
lastName varchar(100) not null
);
-- drop table if exists fruitConsumed;
create table fruitConsumed
( id int auto_increment primary key,
theDate date not null,
fruitId int not null, -- does not really matter. Say, 1=apple, 2=orange from some other table
personId int not null,
qty int not null
);
-- truncate table person;
insert person (firstName,lastName) values
('Dirk','Peters'),
('Dirk','Smith'),
('Jane','Billings');
-- truncate table fruitConsumed;
insert fruitConsumed (theDate,fruitId,personId,qty) values
('2016-10-31',1,1,2),
('2016-10-31',2,1,5),
('2016-10-31',2,2,12),
('2016-11-02',2,2,3);
Requête :
select p.firstName,p.lastName,sum(fc.qty)
from person p
join fruitConsumed fc
on fc.personId=p.id
group by p.firstName,p.lastName;
+-----------+----------+-------------+
| firstName | lastName | sum(fc.qty) |
+-----------+----------+-------------+
| Dirk | Peters | 7 |
| Dirk | Smith | 15 |
+-----------+----------+-------------+
Ce qui précède fonctionne très bien sur MySQL 5.6 et 5.7 quel que soit le paramètre pour ONLY_FULL_GROUP_BY
considérez maintenant
select p.firstName,p.lastName,sum(fc.qty)
from person p
join fruitConsumed fc
on fc.personId=p.id
group by p.firstName;
+-----------+----------+-------------+
| firstName | lastName | sum(fc.qty) |
+-----------+----------+-------------+
| Dirk | Peters | 22 |
+-----------+----------+-------------+
Ce qui précède est souvent acceptable sur MySQL 5.6 sans ONLY_FULL_GROUP_BY
activé et échoue sur 5.7 avec ONLY_FULL_GROUP_BY
activé (erreur 1055). La sortie ci-dessus est essentiellement du charabia. Mais ci-dessous, c'est expliqué un peu :
Nous savons que Dirk, un Dirk, un seul Dirk, est le seul à survivre à la jointure interne. Il y a 2 Dirks. Mais à cause du group by p.firstName
, il nous reste un seul Dirk. Nous avons besoin d'un lastName
. En raison de la non-conformité avec
le standard SQL, MySQL peut autoriser cela avec ONLY_FULL_GROUP_BY
éteindre. Donc, il sélectionne simplement n'importe quel ancien nom de famille. Eh bien, le premier qu'il trouve, et c'est soit dans le cache, soit dans l'ordre physique.
Et c'est parti avec Peters. La somme du nombre de fruits est pour tous les Dirks.
Donc, si vous codez comme ça, le non-conforme ONLY_FULL_GROUP_BY
vous donne du charabia.
Et comme indiqué, MySQL 5.7 est livré par défaut pour ne pas autoriser cela. Mais il est possible de le modifier à l'ancienne si vous le souhaitez.
Il est fortement recommandé de corriger vos requêtes et de laisser ONLY_FULL_GROUP_BY
comme activé.