Преди MySQL 5.7 по подразбиране се разрешава неПЪЛНА group by
. Което означава, че можете да имате група от (която използва агрегатни функции като sum
и max
и count
и group_concat
) с други неагрегирани колони (нека ги наречем NON AGGS
) като първите ви 3 показани не всички част от вашата group by
клауза. Позволява го, но резултатите обикновено се получават по следния начин:
-
Сработи чудесно, защото познавате добре данните си и се опитвате да постигнете ясно
-
Получи се ужасно, защото беше гадно
Преди 5.7, ONLY_FULL_GROUP_BY
съществуваше, но беше изключено по подразбиране.
Така че в MySQL 5.7 идва ONLY_FULL_GROUP_BY
по подразбиране ВКЛ. Като такъв, ако опитате група от, но с не всички NON AGGS
в group by
клауза, ще получите грешка.
Помислете за следния проблем в 5.6 по-долу:
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 |
+------+------+----------+
Това, което се случва по-горе, не е всичко NON AGGS
са в group by
. Връща max(age) от col1. Но тъй като col2
не беше в group by
, той използва Cluster Index или Physical Ordering и му донесе, може би по невнимание (една грешка, грешка), грешна стойност за col2. В зависимост от вашите намерения или познаване на вашите данни или дори грижа. Двигателят не го интересуваше; може би го правиш.
За да избегне тези често срещани грешки или неволно връщане на данни, MySQL 5.7 включва ONLY_FULL_GROUP_BY
по подразбиране.
Във вашия случай грешните редове съставляват резултатите ви вероятно за колони 2 и 3.
Вижте страницата наръчник, озаглавена Обработка на MySQL на GROUP BY .
Пример 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);
Запитване:
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 |
+-----------+----------+-------------+
Горното работи чудесно на MySQL 5.6 и 5.7 независимо от настройката за ONLY_FULL_GROUP_BY
сега помислете
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 |
+-----------+----------+-------------+
Горното често е приемливо за MySQL 5.6 без ONLY_FULL_GROUP_BY
активирано и не работи на 5.7 с ONLY_FULL_GROUP_BY
активиран (грешка 1055). Горният изход е основно глупост. Но по-долу е обяснено донякъде:
Знаем, че Дърк, един Дърк, само един Дърк, е единственият, който оцелява във вътрешното присъединяване. Има 2 Dirks. Но заради group by p.firstName
, остава ни само един Дирк. Нуждаем се от lastName
. Поради несъответствието с
SQL стандарта, MySQL може да позволи това с ONLY_FULL_GROUP_BY
изключен. Така че просто избира всяко старо фамилно име. Е, първият, който намери, и това е или в кеша, или във физическото подреждане.
И това мина с Питърс. Сумата за броя на плодовете е за всички Dirks.
Така че, ако кодирате по този начин, несъответстващият не-ONLY_FULL_GROUP_BY
ви дава глупости.
И както беше посочено, MySQL 5.7 по подразбиране не позволява това. Но може да се настрои по стария начин, ако решите.
Силно препоръчително е да коригирате заявките си и да напуснете ONLY_FULL_GROUP_BY
както е активирано.