Před MySQL 5.7 bylo výchozí nastavení povolit nePLNÉ group by
. Což znamená, že můžete mít skupinu podle (která používá agregační funkce jako sum
a max
a count
a group_concat
) s dalšími neagregovanými sloupci (říkejme jim NON AGGS
) jako vaše první 3 zobrazené ne všechny součástí vaší group by
doložka. Umožnilo to, ale výsledky by obvykle dopadly takto:
-
Fungovalo to skvěle, protože svá data dobře znáte a snažíte se dosáhnout zřetelného
-
Dopadlo to strašně, protože to byl snafu
Před verzí 5.7 ONLY_FULL_GROUP_BY
existoval, ale ve výchozím nastavení byl vypnutý.
V MySQL 5.7 tedy přichází ONLY_FULL_GROUP_BY
výchozí ON. Pokud se pokusíte seskupit podle, ale s ne všemi NON AGGS
v group by
klauzule, dostanete chybu.
Zvažte následující problém v 5.6 níže:
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 |
+------+------+----------+
To, co se děje výše, není všechno NON AGGS
jsou v group by
. Vrací max(věk) pomocí col1. Ale protože col2
nebyl ve group by
, použil Cluster Index nebo Physical Ordering a přinesl mu, možná nedopatřením (snafu, chyba), špatnou hodnotu pro col2. V závislosti na vašich záměrech nebo znalosti vašich dat nebo dokonce péče. Motoru to bylo jedno; možná ano.
Aby se předešlo těmto běžným chybám nebo neúmyslnému návratu dat, MySQL 5.7 zapne ONLY_FULL_GROUP_BY
ve výchozím nastavení.
Ve vašem případě tvoří vaše výsledky pravděpodobně pro sloupce 2 a 3 nesprávné řádky.
Viz manuálovou stránku s názvem MySQL Handling of GROUP BY .
Příklad 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);
Dotaz:
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 |
+-----------+----------+-------------+
Výše uvedené funguje skvěle na MySQL 5.6 a 5.7 bez ohledu na nastavení pro ONLY_FULL_GROUP_BY
nyní zvažte
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 |
+-----------+----------+-------------+
Výše uvedené je často přijatelné na MySQL 5.6 bez ONLY_FULL_GROUP_BY
povoleno a selže ve verzi 5.7 s ONLY_FULL_GROUP_BY
povoleno (chyba 1055). Výše uvedený výstup je v podstatě blábol. Ale níže je to trochu vysvětleno:
Víme, že Dirk, Dirk, jen jeden Dirk, je jediný, kdo přežije vnitřní spojení. Jsou tam 2 Dirkové. Ale kvůli group by p.firstName
, zbyl nám jen jeden Dirk. Potřebujeme lastName
. Vzhledem k neshodě s
standardem SQL to může MySQL povolit s ONLY_FULL_GROUP_BY
vypnutý. Takže to prostě vybere jakékoli staré příjmení. No, první, kterou najde, a to je buď v mezipaměti, nebo ve fyzickém uspořádání.
A šlo to s Petersem. Součet počtu ovoce je pro všechny Dirky.
Pokud tedy kódujete takto, nevyhovující nevyhovující ONLY_FULL_GROUP_BY
dává vám blábol.
A jak bylo uvedeno, MySQL 5.7 se standardně dodává tak, že to neumožňuje. Pokud si to však přejete, lze jej upravit na starý způsob.
Důrazně doporučujeme, abyste své dotazy opravili a opustili ONLY_FULL_GROUP_BY
jako povoleno.