Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Existe uma maneira de mostrar uma cláusula WHERE apenas para um campo no MySQL?


Antes do MySQL 5.7, o padrão era permitir group by não FULL . O que significa que você pode ter um grupo por (que usa funções agregadas como sum e max e count e group_concat ) com outras colunas não agregadas (vamos chamá-las de NON AGGS ) como seus 3 primeiros mostrados nem todos parte do seu group by cláusula. Permitiu, mas os resultados normalmente funcionariam assim:

  • Funcionou muito bem porque você conhece bem seus dados e está tentando alcançar um

  • Deu muito certo porque foi um snafu

Antes de 5.7, ONLY_FULL_GROUP_BY existia, mas estava DESLIGADO por padrão.

Então no MySQL 5.7 vem o ONLY_FULL_GROUP_BY padrão LIGADO. Assim, se você tentar agrupar por, mas com nem todos o NON AGGS no group by cláusula, você obteria um erro.

Considere o seguinte problema em 5.6 abaixo:
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 |
+------+------+----------+

O que acontece acima não é tudo NON AGGS estão no group by . Ele retorna o max(idade) por col1. Mas como col2 não estava no group by , ele usou o Cluster Index ou Physical Ordering e trouxe, inadvertidamente, talvez (um snafu, um erro), o valor errado para col2. Dependendo de suas intenções ou conhecendo seus dados ou até mesmo se importando. O motor não se importava; talvez você faça.

Para evitar esses erros comuns ou retorno de dados inadvertido, o MySQL 5.7 ativa ONLY_FULL_GROUP_BY por padrão.

No seu caso, as linhas erradas estão compondo seus resultados presumivelmente para as colunas 2 e 3.

Consulte a página do manual intitulada Manipulação MySQL de GROUP BY .

Exemplo 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);

Inquerir:
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 |
+-----------+----------+-------------+

O acima funciona muito bem no MySQL 5.6 e 5.7, independentemente da configuração para ONLY_FULL_GROUP_BY

agora 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 |
+-----------+----------+-------------+

O acima é geralmente aceitável no MySQL 5.6 sem ONLY_FULL_GROUP_BY ativado e falha em 5.7 com ONLY_FULL_GROUP_BY habilitado (erro 1055). A saída acima é basicamente sem sentido. Mas abaixo é explicado um pouco:

Sabemos que Dirk, um Dirk, apenas um Dirk, é o único a sobreviver à junção interna. Existem 2 Dirks. Mas por causa do group by p.firstName , ficamos com apenas um Dirk. Precisamos de um lastName . Devido à não conformidade com
o padrão SQL, o MySQL pode permitir isso com ONLY_FULL_GROUP_BY desligado. Então, ele apenas escolhe qualquer sobrenome antigo. Bem, o primeiro que ele encontra, e que está no cache ou no ordenamento físico.

E foi com Peters. A soma da contagem de frutas é para todos os Dirks.

Portanto, se você codificar assim, a não conformidade não-ONLY_FULL_GROUP_BY te dá um gabarito.

E como dito, o MySQL 5.7 vem por padrão para não permitir isso. Mas é ajustável à maneira antiga, se você escolher.

É altamente recomendável que você corrija suas consultas e deixe ONLY_FULL_GROUP_BY como habilitado.