Antes de MySQL 5.7, el valor predeterminado era permitir grupos group by
. Lo que significa que puede tener un grupo por (que usa funciones agregadas como sum
y max
y count
y group_concat
) con otras columnas no agregadas (llamémoslas NON AGGS
) como tus primeros 3 mostrados no todos parte de tu group by
cláusula. Lo permitió, pero los resultados normalmente serían así:
-
Funcionó muy bien porque conoce bien sus datos y está tratando de lograr una distinción
-
Funcionó horrible porque fue un fiasco
Antes de 5.7, ONLY_FULL_GROUP_BY
existía pero estaba APAGADO de forma predeterminada.
Así que en MySQL 5.7 viene el ONLY_FULL_GROUP_BY
por defecto ENCENDIDO. Como tal, si intenta un grupo por, pero con no todos el NON AGGS
en el group by
cláusula, obtendrá un error.
Considere el siguiente problema en 5.6 a continuación:
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 |
+------+------+----------+
Lo que sucede arriba no es todo NON AGGS
están en el group by
. Devuelve el máximo (edad) por col1. Pero desde col2
no estaba en el group by
, usó el Índice de clúster o el Ordenamiento físico y trajo, quizás sin darse cuenta (una metedura de pata, un error), el valor incorrecto para col2. Dependiendo de tus intenciones o conociendo tus datos o incluso cuidando. Al motor no le importaba; quizás lo hagas.
Para evitar estos errores comunes o la devolución inadvertida de datos, MySQL 5.7 activa ONLY_FULL_GROUP_BY
por defecto.
En su caso, las filas incorrectas conforman sus resultados, presumiblemente para las columnas 2 y 3.
Consulte la página del manual titulada MySQL Handling of GROUP BY .
Ejemplo 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);
Consulta:
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 |
+-----------+----------+-------------+
Lo anterior funciona muy bien en MySQL 5.6 y 5.7 independientemente de la configuración de ONLY_FULL_GROUP_BY
ahora considere
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 |
+-----------+----------+-------------+
Lo anterior suele ser aceptable en MySQL 5.6 sin ONLY_FULL_GROUP_BY
habilitado y falla en 5.7 con ONLY_FULL_GROUP_BY
activado (error 1055). La salida anterior es básicamente un galimatías. Pero a continuación se explica un poco:
Sabemos que Dirk, un Dirk, solo un Dirk, es el único que sobrevivió a la unión interna. Hay 2 Dirks. Pero debido al grupo group by p.firstName
, nos quedamos con un solo Dirk. Necesitamos un lastName
. Debido a la no conformidad con
el estándar SQL, MySQL puede permitir esto con ONLY_FULL_GROUP_BY
apagado. Entonces solo elige cualquier apellido antiguo. Bueno, el primero que encuentra, y ese está en caché o en el ordenamiento físico.
Y se fue con Peters. La suma del conteo de frutas es para todos los Dirks.
Entonces, si codificas así, el no ONLY_FULL_GROUP_BY
no conforme te da un galimatías.
Y como se indicó, MySQL 5.7 se envía de forma predeterminada para no permitir esto. Pero se puede ajustar a la forma antigua si lo deseas.
Se recomienda encarecidamente que arregle sus consultas y deje ONLY_FULL_GROUP_BY
como habilitado.