only_full_group_by模式有什么好处?

Roc*_*tar 11 mysql sql

我更新了mysql,我从MySQL 5.6.17版本转到版本5.7.14

因为我的SQL查询有错误

实际上,我的许多查询都是这样的:

SELECT count (id) as nbr, lic from prep WHERE key = '18'
Run Code Online (Sandbox Code Playgroud)

我有这个错误:

1140 - 在没有GROUP BY的聚合查询中,SELECT列表的表达式#2包含非聚合列'operator.preparation.orig_lic'; 这与sql_mode = only_full_group_by不兼容

经过一些研究,我了解到Mysql 5.7.14默认激活ONLY_FULL_GROUP_BY

为什么默认启用?

什么是最佳解决方案(性能)?禁用ONLY_FULL_GROUP_BY或在我的查询中添加"分组依据"?

谢谢

Ahm*_*aki 12

only_full_group_by = on告诉 MySQL 引擎:GROUP BY当你对显示什么结果有疑问并抛出错误时不要申请。仅当命令明确告诉您要做什么时才应用它。即当命令完整且完整时!

only_full_group_by = off告诉 MySQL 引擎:始终应用GROUP BY,如果您对选择的结果有疑问,请随机选择一个!

使用GROUP BY得当是不会关掉的 !

例子:

表:用户

 id   |  name
----------------
  1      ali
  2      john
  3      ali
Run Code Online (Sandbox Code Playgroud)

在列GROUP BY上使用时name

SELECT * FROM users GROUP BY name;
Run Code Online (Sandbox Code Playgroud)

有两种可能的结果:

  1      ali
  2      john     
Run Code Online (Sandbox Code Playgroud)

或者

  2      john
  3      ali
Run Code Online (Sandbox Code Playgroud)

MYSQL不知道选择什么结果!因为有不同的ids 但两者都有name=ali

解决方案1:

只选择name字段:

SELECT name FROM users GROUP BY name;
Run Code Online (Sandbox Code Playgroud)

结果:

  ali
  john     
Run Code Online (Sandbox Code Playgroud)

这是一个完美的解决方案。删除令人GROUP BY困惑的列。这意味着你知道你在做什么。通常,您不需要
这些列,但如果您需要它们,请转到解决方案 3!

解决方案2:

关闭only_full_group_by。MYSQL 将随机向您显示两种可能的结果之一!(如果你真的不在乎id它会选择什么也没关系)

解决方案3

使用Aggregate类似MIN(),的函数MAX()来帮助 MYSQL 决定它必须选择什么。

例如,我想要最小值id

SELECT MIN(id), name FROM users GROUP BY name;
Run Code Online (Sandbox Code Playgroud)

结果:

  1      ali
  2      john     
Run Code Online (Sandbox Code Playgroud)

它将选择ali具有最小值的行id

  • **感谢**对多年来在我看来奇怪、无益、痛苦和武断的规则的精彩解释,只会激怒开发人员。 (3认同)

sca*_*dge 6

正确的解决方案是添加您分组的列:

SELECT count (id) as nbr, lic 
from prep 
WHERE key = '18'
group by lic
Run Code Online (Sandbox Code Playgroud)

对于性能,这取决于您拥有的索引。

ONLY_FULL_GROUP_BY 是 SQL 中聚合函数的正常行为,采用 5.7 以避免对非聚合列结果的临时结果产生歧义。


yan*_*234 5

“最佳”解决方案是做正确的事情并通过添加来修复查询group by,而不是覆盖抛出的错误。如果用ONLY_FULL_GROUP_BY错误覆盖错误,您的经历将消失,但是这样做可能会导致两个新错误:

  1. 包含非聚集值的聚集值的意外结果,这是您的错误试图避免的问题。

  2. 无法在其他环境上执行查询。如果您需要切换设置或将代码提供给不使用此数据库的其他人,查询将再次引发错误。如果您习惯于改写错误或其他错误,则您的代码可能对其他人不可用,从而严重削弱了代码的实用性。

通常,如果收到错误,请修复它,而不仅仅是告诉编译器/优化器忽略它。