sql >> Base de Datos >  >> RDS >> Mysql

¿Hay alguna forma de mostrar una cláusula WHERE solo para un campo en MySQL?

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.