MySQL ONLY_FULL_GROUP_BY 问题一则

336 阅读2分钟

问题


白天收到一个慢查询的告警,发现了一个很奇特的语句,简化后,摘要如下:

SELECT c.`name`,NOW(),COUNT(1) 'FROM `order` o 
LEFT JOIN `shop` c ON o.`ShopId`=c.`shopId`
WHERE o.`STATUS`IN('L') 
GROUP BY o.`ShopId`

当前数据库版本为5.7.19,sql_mode为 ONLY_FULL_GROUP_BY,如有不同情况,请以实际环境为准

有经验的朋友,大概一眼就会发现问题所在,在ONLY_FULL_GROUP_BY的严格模式下,select 查询列未包含在group by的子句中,该语句应当会执行出错,抛出错误如:

1055 - Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'order.ShopId' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

但实际该语句仍旧能够跑成功,问题出在哪儿?查询表结构后发现了端倪:

desc order

Field	Type	Null	Key	Default	Extra
shopId	char(15)	NO	PRI		
...

order表中shopid为主键

实验


那么构造一个类似的表进行试验:


create table testa
(id int primary key auto_increment,
name varchar(10) unique key ,
statu varchar(10)
);


insert into testa (name,statu) values ('a','Y');
insert into testa (name,statu) values ('b','Y');
insert into testa (name,statu) values ('c','Y');
insert into testa (name,statu) values ('d','Y');
insert into testa (name,statu) values ('e','Y');
insert into testa (name,statu) values ('f','Y');


select statu,count(1) from testa
group by id;

以上语句能够执行成功,翻阅官网相关文档:

image.png

image.png

提到sql1999规范中,如果custid是主键,则允许这种聚合;

总结


oracle或者sql server中如上语句执行会异常,mysql兼容了group by主键这种特殊情况,实际情况下,还是建议按照严格的逻辑去写聚合语句,毕竟按照主键分组,如果主键与查询列不是一对一的关系,可能最终聚合出来的结果和实际需要的就会产生差距。

参考文档:

dev.mysql.com/doc/refman/…

dev.mysql.com/doc/refman/…