Før MySQL 5.7 var standarden at tillade ikke FULD group by
. Hvilket betyder, at du kan have en gruppe efter (der bruger aggregerede funktioner som sum
og max
og count
og group_concat
) med andre ikke-aggregerede kolonner (lad os kalde dem NON AGGS
) synes godt om dine første 3 viste ikke alle en del af din group by
klausul. Det tillod det, men resultaterne ville typisk virke sådan her:
-
Det fungerede godt, fordi du kender dine data godt og forsøger at opnå en distinkt
-
Det fungerede forfærdeligt, fordi det var et snavs
Før 5.7, ONLY_FULL_GROUP_BY
eksisterede, men den var som standard slået FRA.
Så i MySQL 5.7 følger ONLY_FULL_GROUP_BY
standard ON. Som sådan, hvis du forsøger en gruppe af, men med ikke alle NON AGGS
i group by
klausul, ville du få en fejl.
Overvej følgende problem i 5.6 nedenfor:
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 |
+------+------+----------+
Det, der sker ovenfor, er ikke alle NON AGGS
er i group by
. Det returnerer max(alder) ved col1. Men siden col2
var ikke i group by
, den brugte Cluster Index eller Physical Ordering og bragte det, måske utilsigtet (en snafu, en fejl), den forkerte værdi for col2. Afhængig af dine intentioner eller kendskab til dine data eller endda omsorg. Motoren var ligeglad; måske gør du det.
For at undgå disse almindelige fejl eller utilsigtet dataretur, aktiverer MySQL 5.7 ONLY_FULL_GROUP_BY
som standard.
I dit tilfælde udgør de forkerte rækker dine resultater, formentlig for kolonne 2 og 3.
Se manualsiden med titlen MySQL-håndtering af GROUP BY .
Eksempel 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);
Forespørgsel:
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 |
+-----------+----------+-------------+
Ovenstående fungerer godt på MySQL 5.6 og 5.7 uanset indstillingen for ONLY_FULL_GROUP_BY
overvej nu
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 |
+-----------+----------+-------------+
Ovenstående er ofte acceptabelt på MySQL 5.6 uden ONLY_FULL_GROUP_BY
aktiveret og fejler i 5.7 med ONLY_FULL_GROUP_BY
aktiveret (fejl 1055). Ovenstående output er dybest set volapyk. Men nedenfor er det forklaret lidt:
Vi ved, at Dirk, en Dirk, bare en Dirk, er den eneste, der overlever den indre sammenføjning. Der er 2 Dirks. Men på grund af group by p.firstName
, står vi tilbage med kun én Dirk. Vi har brug for et lastName
. På grund af manglende overensstemmelse med
SQL-standarden kan MySQL tillade dette med ONLY_FULL_GROUP_BY
slukket. Så den vælger bare et hvilket som helst gammelt efternavn. Nå, den første den finder, og det er enten i cachen eller den i den fysiske bestilling.
Og det gik med Peters. Frugttællingssummen er for alle Dirks.
Så hvis du koder sådan, vil den ikke-overensstemmende ikke-ONLY_FULL_GROUP_BY
giver dig volapyk.
Og som sagt, MySQL 5.7-skibe tillod som standard ikke dette. Men det kan justeres til den gamle måde, hvis du vælger det.
Det anbefales stærkt, at du løser dine forespørgsler og lader ONLY_FULL_GROUP_BY
som aktiveret.