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 BY
。 仅在Group 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 不知道选择什么结果!因为有不同的id
s,但都有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 模式有啥好处?的主要内容,如果未能解决你的问题,请参考以下文章