Före MySQL 5.7 var standarden att tillåta icke FULL group by
. Vilket betyder att du kan ha en grupp efter (som använder aggregerade funktioner som sum
och max
och count
och group_concat
) med andra icke aggregerade kolumner (låt oss kalla dem NON AGGS
) gillar dina första 3 visade inte alla en del av din group by
klausul. Det tillät det men resultaten skulle vanligtvis se ut så här:
-
Det fungerade utmärkt eftersom du känner till din data väl och försöker uppnå en distinkt
-
Det gick hemskt eftersom det var ett smyg
Före 5.7, ONLY_FULL_GROUP_BY
existerade men den var avstängd som standard.
Så i MySQL 5.7 kommer ONLY_FULL_GROUP_BY
förinställd PÅ. Som sådan om du försöker en grupp av, men med inte alla NON AGGS
i group by
klausul skulle du få ett fel.
Tänk på följande problem i 5.6 nedan:
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 som händer ovan är inte alla NON AGGS
finns i group by
. Den returnerar max(åldern) med kol1. Men eftersom col2
fanns inte i group by
, använde den Cluster Index eller Physical Ordering och gav det, kanske oavsiktligt (en snafu, ett misstag), fel värde för col2. Beroende på dina avsikter eller att känna till dina data eller till och med bry sig. Motorn brydde sig inte; kanske du gör det.
För att undvika dessa vanliga misstag eller oavsiktlig dataretur, aktiverar MySQL 5.7 ONLY_FULL_GROUP_BY
som standard.
I ditt fall utgör fel rader dina resultat förmodligen för kolumn 2 och 3.
Se manualsidan med titeln MySQL-hantering av GROUP BY .
Exempel 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);
Fråga:
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 |
+-----------+----------+-------------+
Ovanstående fungerar utmärkt på MySQL 5.6 och 5.7 oavsett inställningen för ONLY_FULL_GROUP_BY
överväg 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 |
+-----------+----------+-------------+
Ovanstående är ofta acceptabelt på MySQL 5.6 utan ONLY_FULL_GROUP_BY
aktiverad och misslyckas på 5.7 med ONLY_FULL_GROUP_BY
aktiverad (fel 1055). Ovanstående utdata är i grunden struntprat. Men nedan förklaras det något:
Vi vet att Dirk, en Dirk, bara en Dirk, är den ende som överlever den inre sammanfogningen. Det finns 2 Dirks. Men på grund av group by p.firstName
, vi har bara en Dirk kvar. Vi behöver ett lastName
. På grund av bristande överensstämmelse med
SQL-standarden kan MySQL tillåta detta med ONLY_FULL_GROUP_BY
avstängd. Så den väljer bara vilket gammalt efternamn som helst. Tja, den första den hittar, och det är antingen i cachen eller den i den fysiska beställningen.
Och det gick med Peters. Frukträkningssumman är för alla Dirks.
Så om du kodar så här, den icke-överensstämmande icke-ONLY_FULL_GROUP_BY
ger dig skratt.
Och som sagt, MySQL 5.7 levererade som standard att inte tillåta detta. Men det går att justera till det gamla sättet om du vill.
Vi rekommenderar starkt att du fixar dina frågor och lämnar ONLY_FULL_GROUP_BY
som aktiverat.