Przed MySQL 5.7 domyślnie zezwalało na nie PEŁNE group by
. Co oznacza, że możesz mieć grupę według (która używa funkcji agregujących, takich jak sum
i max
i count
i group_concat
) z innymi kolumnami niezagregowanymi (nazwijmy je NON AGGS
) jak Twoje pierwsze 3 pokazane nie wszystkie część twojej group by
klauzula. Pozwoliło na to, ale wyniki zwykle wyglądały tak:
-
Udało się to świetnie, ponieważ dobrze znasz swoje dane i starasz się osiągnąć wyraźny
-
Udało się okropnie, bo to było snafu
Przed wersją 5.7 ONLY_FULL_GROUP_BY
istniał, ale był domyślnie WYŁĄCZONY.
Tak więc w MySQL 5.7 pojawia się ONLY_FULL_GROUP_BY
domyślnie WŁ. Jako takie, jeśli próbujesz grupować, ale z nie wszystkimi NON AGGS
w grupie group by
klauzula, otrzymasz błąd.
Rozważ następujący problem w 5.6 poniżej:
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 dzieje się powyżej, to nie tylko NON AGGS
są w group by
. Zwraca max(age) przez col1. Ale ponieważ col2
nie był w grupie group by
, użył Indeksu Klastrów lub Porządku Fizycznego i przyniósł mu, być może nieumyślnie (snafu, pomyłka), niewłaściwą wartość dla col2. W zależności od twoich intencji lub znajomości danych, a nawet troski. Silnik nie przejmował się; być może tak.
Aby uniknąć tych typowych błędów lub nieumyślnego zwracania danych, MySQL 5.7 włącza ONLY_FULL_GROUP_BY
domyślnie.
W Twoim przypadku nieprawidłowe wiersze składają się na wyniki prawdopodobnie w kolumnach 2 i 3.
Zobacz stronę podręcznika zatytułowaną Obsługa MySQL dla GROUP BY .
Przykład 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);
Zapytanie:
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 |
+-----------+----------+-------------+
Powyższe działa świetnie na MySQL 5.6 i 5.7 niezależnie od ustawienia dla ONLY_FULL_GROUP_BY
teraz rozważ
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 |
+-----------+----------+-------------+
Powyższe jest często akceptowalne w MySQL 5.6 bez ONLY_FULL_GROUP_BY
włączone i nie działa w wersji 5.7 z ONLY_FULL_GROUP_BY
włączone (błąd 1055). Powyższe dane wyjściowe są w zasadzie bełkotem. Ale poniżej jest to nieco wyjaśnione:
Wiemy, że Dirk, Dirk, tylko jeden Dirk, jest jedynym, który przetrwał wewnętrzne połączenie. Jest 2 sztyletów. Ale z powodu group by p.firstName
, zostaje nam tylko jeden Dirk. Potrzebujemy lastName
. Ze względu na niezgodność
standardu SQL, MySQL może na to pozwolić z ONLY_FULL_GROUP_BY
wyłączony. Więc po prostu wybiera stare nazwisko. Cóż, pierwszy, który znajdzie, i to albo w pamięci podręcznej, albo ten w porządku fizycznym.
I poszło z Petersem. Suma liczby owoców dotyczy wszystkich Dirków.
Więc jeśli kodujesz w ten sposób, niezgodny kod niezgodny ONLY_FULL_GROUP_BY
daje bełkot.
Jak już wspomniano, statki MySQL 5.7 domyślnie nie zezwalały na to. Ale można to zmienić w stary sposób, jeśli wybierzesz.
Zdecydowanie zaleca się poprawienie zapytań i pozostawienie ONLY_FULL_GROUP_BY
jako włączone.