参考资料
发生的问题
当我写下如下sql进行分组查询时:
SELECT * FROM `table` GROUP BY update_time;
爆出如下错误:
> 1055 - Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'sentence. 'id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
翻译的意思是:
SELECT列表的表达式#1不在groupby子句中,并且包含非聚合列的sentence。 'id'在功能上不依赖于GROUP BY子句中的列; 这与sql_mode=only_full_group_by不兼容
我理解的意思是:
如果想正常使用,需要GROUP BY后列表和select后列表保持一致,或者GROUP BY后跟个聚合列,比如主键。
发生的原因分析
mysql 5.7.5之后,实现了功能依赖检测,即默认开启sql_mode=only_full_group_by。
官方原话该指令代表着:拒绝SELECT列表、HAVING条件或 ORDER BY列表引用非聚合列的查询,这些列既不在GROUP BY子句中命名,也不在功能上依赖于它们。
如果不遵守这个规则就可能会爆出此错误。具体看特性解析。
only_full_group_by特性解析
说明在这种模式下如何进行sql书写,以及该模式的优劣分析。
引用聚合列
# GROUP BY 引用聚合列id为条件分组,可以执行
SELECT * FROM `table` GROUP BY id;
引用非聚合列但限定单一结果
# GROUP BY 引用非聚合列 update_time
# 但是由于 WHERE 语句将查询结果限制为一条结果,可以执行,仅限一条结果
SELECT * FROM `table` WHERE id = 1 GROUP BY update_time;
any_value()
# 通过any_value()函数可以屏蔽某个字段被该模式的影响
SELECT ANY_VALUE(update_time) AS update_time FROM `table` GROUP BY update_time;
only_full_group_by模式优劣
优
官方话:如果禁用此模式,则服务器可以从每个组中自由选择任何值,因此除非它们相同,否则选择的值是不确定的,这可能不是您想要的。
个人理解:如果不使用此模式,分组后的每组“代表”可能会被选择成你不想要的那个代表,除非这组“代表”都相同,如果分组的“代表”被选择成你不想要的那个,你后序的操作也会受到影响。
劣
个人感觉:貌似他的优点不是很大,而启用后,对于已经确定不会有影响的sql,又需要诸多额外操作以去除被这种模式带来的影响。但是个人学识尚浅,各位斟酌理解。
解决方案
关闭模式
去网上搜,一堆
遵守特性
参见特性解析,主要是any_value()