only_full_group_by 模式有啥好处?

Posted

技术标签:

【中文标题】only_full_group_by 模式有啥好处?【英文标题】:What are the benefits of only_full_group_by mode?only_full_group_by 模式有什么好处? 【发布时间】:2018-01-11 01:12:35 【问题描述】:

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

因为我的 sql 查询有错误

确实,我的许多查询看起来像这样:

SELECT count (id) as nbr, lic from prep WHERE key = '18'

我有这个错误:

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 或在我的查询中添加“分组依据”?

谢谢

【问题讨论】:

only_full_group_by 强制您命名 GROUP BY 原因中的所有 SELECT 字段.. 这样您就不能编写错误的 GROUP BY 查询而不命名所有字段...阅读此psce.com/en/blog/2012/05/15/… @RaymondNijland 关于 GROUP BY 模式“ONLY_FULL_GROUP_BY”的精彩帖子。我正在寻找这样的演示文稿。非常感谢!!! 【参考方案1】:

only_full_group_by = on 告诉 MySQL 引擎:当您对要显示的结果有疑问并抛出错误时,不要应用 GROUP BYGroup By 明确告诉您该做什么时应用它。即当Group By 完整且完美时!

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

如果你正确使用GROUP BY,你不必关闭它!

示例:

表:用户

 id   |  name
----------------
  1      ali
  2      john
  3      ali

当您在name 列上使用GROUP BY 时:

SELECT * FROM users GROUP BY name;

有两种可能的结果:

  1      ali
  2      john     

  2      john
  3      ali

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

解决方案 1:

只选择name 字段:

SELECT name FROM users GROUP BY name;

结果:

  ali
  john     

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

解决方案 2:

关闭only_full_group_by。 MYSQL 将选择两种可能的结果之一随机!! (如果您并不真正关心 id 会选择什么也没关系,但请记住在查询后立即打开它,以防止将来 groupBys 出现意外行为)

解决方案3

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

例如:

SELECT MAX(id), name FROM users GROUP BY name;

结果:

  2      john     
  3      ali

它将选择ali 具有最大id 的行。

【讨论】:

【参考方案2】:

“最佳”解决方案是做正确的事情并通过添加group by 来修复您的查询,而不是覆盖引发的错误。如果您使用ONLY_FULL_GROUP_BY 覆盖错误,您遇到的错误将会消失,但您可能会因此遇到两个新错误:

    包含聚合值和非聚合值的意外结果,您的错误试图防止的问题。

    无法在其他环境中执行您的查询。如果您需要切换设置或将代码提供给不使用此数据库的其他人,查询将再次抛出错误。如果您养成了覆盖错误或其他错误的习惯,您的代码可能对其他人无法使用并严重削弱它的实用性。

一般来说,如果您收到错误,请修复它,而不是告诉编译器/优化器忽略它。

【讨论】:

添加组并不总是返回我们想要的。例如,SELECT sum(amount) as totalAmount, IF(action="+", amount, 0) as totalInGoing FROM transactions` where account_id = 32099` 此查询使用 ONLY_FULL_GROUP_BY 模式,需要 GROUP BY action 才能工作。这使得 totalInGoing 无用,因为它将返回严重的行。【参考方案3】:

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

SELECT count (id) as nbr, lic 
from prep 
WHERE key = '18'
group by lic

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

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

【讨论】:

谢谢,但它改变了一些事情来做组在 id 或 lic 上? 完全更改 .. 您在 group by 中设置的列用作聚合的键 .. 例如:如果您想要具有相同 lic 的行数,您可以使用 group by lic .. 否则,如果您想要另一列的行数,而不是其他列名.. 如果你是按 lic 计算非空 id 组的数量 谢谢,但在这样的查询中:SELECT user_name, valid.user, via, master, nb_jours, min(date) as date_min from valid, users_instruction where is_finish = 0 and user = cust_id和 users_instruction.br = valid.br group by master order by date_min ASC 我不能使用 Group by 吗? 使用 group by 你应该在 group by 中拥有所有不在聚合函数中的列( user_name 、 valid.user 、 via 、 master 、 nb_jours )不仅是 master .. 但这似乎是一个新请求.. 尝试使用适当的数据样本和预期结果添加一个新问题

以上是关于only_full_group_by 模式有啥好处?的主要内容,如果未能解决你的问题,请参考以下文章

桥接模式有啥好处[关闭]

android中ViewHolder模式有啥好处?

这种开关/模式匹配的想法有啥好处吗?

在 avro 中存储模式有啥好处?

在星型模式表设计中包含关系有啥好处?

站库分离有啥好处,会不会更快?