Vóór MySQL 5.7 was de standaardinstelling om niet-VOLLEDIGE group by
toe te staan . Wat betekent dat je een groep kunt hebben op (die gebruikmaakt van geaggregeerde functies zoals sum
en max
en count
en group_concat
) met andere niet-geaggregeerde kolommen (laten we ze NON AGGS
noemen) ) vind je eerste 3 leuk niet allemaal onderdeel van je group by
clausule. Het stond het toe, maar de resultaten zouden normaal gesproken als volgt uitpakken:
-
Het werkte geweldig omdat u uw gegevens goed kent en probeert een duidelijk
-
Het werkte verschrikkelijk omdat het een snafu was
Vóór 5.7, ONLY_FULL_GROUP_BY
bestond maar was standaard UITGESCHAKELD.
Dus in MySQL 5.7 komt de ONLY_FULL_GROUP_BY
standaard AAN. Als zodanig als u een groep probeert op, maar met niet alle de NON AGGS
in de group by
clausule, krijgt u een Error.
Beschouw het volgende probleem in 5.6 hieronder:
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 |
+------+------+----------+
Wat hierboven gebeurt, is niet alle NON AGGS
zijn in de group by
. Het retourneert de max (leeftijd) door col1. Maar sinds col2
zat niet in de group by
, het gebruikte de Cluster Index of Physical Ordering en bracht het, per ongeluk misschien (een snafu, een fout), de verkeerde waarde voor col2. Afhankelijk van uw bedoelingen of wetende uw gegevens of zelfs zorgzaam. De motor maakte het niet uit; misschien wel.
Om deze veelvoorkomende fouten of onbedoelde gegevensteruggave te voorkomen, schakelt MySQL 5.7 ONLY_FULL_GROUP_BY
in standaard.
In uw geval vormen de verkeerde rijen uw resultaten vermoedelijk voor de kolommen 2 en 3.
Zie de pagina met de handleiding met de titel MySQL-afhandeling van GROUP BY .
Voorbeeld 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);
Vraag:
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 |
+-----------+----------+-------------+
Het bovenstaande werkt prima op MySQL 5.6 en 5.7, ongeacht de instelling voor ONLY_FULL_GROUP_BY
overweeg 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 |
+-----------+----------+-------------+
Het bovenstaande is vaak acceptabel op MySQL 5.6 zonder ONLY_FULL_GROUP_BY
ingeschakeld en mislukt op 5.7 met ONLY_FULL_GROUP_BY
ingeschakeld (fout 1055). De bovenstaande uitvoer is eigenlijk wartaal. Maar hieronder wordt het enigszins uitgelegd:
We weten dat Dirk, een Dirk, gewoon ene Dirk, de enige is die de binnenband overleeft. Er zijn 2 Dirks. Maar vanwege de group by p.firstName
, we hebben nog maar één Dirk over. We hebben een lastName
nodig . Vanwege de niet-conformiteit met
de SQL-standaard, kan MySQL dit toestaan met ONLY_FULL_GROUP_BY
uitgeschakeld. Dus het kiest gewoon een oude achternaam. Welnu, de eerste die het vindt, en dat is ofwel in de cache of degene in de fysieke bestelling.
En het ging met Peters. De fruittelsom is voor alle Dirks.
Dus als je op deze manier codeert, wordt de niet-conforme niet-ONLY_FULL_GROUP_BY
geeft je wartaal.
En zoals gezegd, MySQL 5.7-schepen stonden dit standaard niet toe. Maar het is aanpasbaar naar de oude manier als je ervoor kiest.
Het wordt ten zeerste aanbevolen dat u uw vragen oplost en ONLY_FULL_GROUP_BY
. verlaat zoals ingeschakeld.