mysql 5.6 是不是有 ANY_VALUE 功能?

Posted

技术标签:

【中文标题】mysql 5.6 是不是有 ANY_VALUE 功能?【英文标题】:Is there ANY_VALUE capability for mysql 5.6?mysql 5.6 是否有 ANY_VALUE 功能? 【发布时间】:2016-09-02 12:41:18 【问题描述】:

目前我正在开发 mysql 5.7 和生产中的 5.6。每次我在开发中使用 group by 运行查询时,我都会收到一些错误,例如“错误代码:1055。SELECT 列表的表达式 #1 不在 GROUP BY 中”

这是查询。

SELECT c.id, c.name, i.* 
 FROM countries c, images i 
WHERE i.country_id = c.id
GROUP BY c.id; Fixed for 5.7; 

SELECT c.id, c.name,
       ANY_VALUE(i.url) url, 
       ANY_VALUE(i.lat) lat, 
       ANY_VALUE(i.lng) lng 
  FROM countries c, images i
 WHERE i.country_id = c.id
 GROUP BY c.id;

为了解决我使用 5.7 ANY_VALUE 中的 mysql 函数,但主要问题是它在 mysql 5.6 中不可用

因此,如果我修复了用于开发的 sql 语句,我将在生产中遇到错误。

你知道 mysql 5.6 中 ANY_VALUE 函数的任何解决方案或 polifill 吗?

【问题讨论】:

为什么不直接使用MINMAX 【参考方案1】:

您误用了notorious nonstandard MySQL extension to GROUP BY。标准 SQL 将始终拒绝您的查询,因为您提到的列不是聚合的,也没有在 GROUP BY 中提及。在您的开发系统中,您正尝试使用ANY_VALUE() 解决这个问题。

在生产中,你可以关闭ONLY_FULL_GROUP_BY MySQL Mode.尝试做this:

  SET @mode := @@SESSION.sql_mode;
  SET SESSION sql_mode = '';
  /* your query here */
  SET SESSION sql_mode = @mode;

这将允许 MySQL 接受您的查询。

但是看,您的查询并不正确。当您可以说服它运行时,它会从images 表中返回一个随机选择的行。这种不确定性通常会给用户和您的技术支持人员造成混淆。

为什么不让查询更好,所以它选择了一个特定的图像。如果您的 images 表有一个自动增量 id 列,您可以这样做以选择“第一个”图像。

SELECT c.id, c.name, i.*
  FROM countries c
  LEFT JOIN (
       SELECT MIN(id) id, country_id
         FROM images
        GROUP BY country_id
       ) first ON c.id = first.country_id
  LEFT JOIN images i ON first.id = i.id

这将在每个国家/地区返回一行,并显示可预测的图像。

【讨论】:

pd:我讨厌子选择!他们不是更慢吗? 我猜,subselect 是指像我一样加入聚合。根据我的经验,它们的性能与其他查询性能一样,取决于索引的选择和其他类似的东西。我展示的那个可以大大加快查询速度。它减少了要考虑的行数。并且聚合查询可以使用效率惊人的松散索引扫描来处理它的事情。阅读相关内容。 注意:ANY_VALUE 的执行速度比 MIN 快得多,因为 MIN 需要对数据集进行全面评估。 MIN 仅应在您希望表 'i' 中的多行用于表 'c' 中的每一行时使用,但是当您加入时,每个 'i' 有许多 'c' 值,那么 ANY_VALUE 应该是首选,因为无论如何所有值都将相同。【参考方案2】:

您可以使用MINMAX 聚合函数来代替ANY_VALUE

或者,您可以考虑不设置ONLY_FULL_GROUP_BY SQL 模式,这是默认为 MySql 5.7 设置的,它负责您在 MySql 5.6 中体验到的差异。然后,您可以延迟查询的更新,直到您将所有环境迁移到 MySql 5.7。

两者中哪一个是更好的选择,值得商榷,但从长远来看,调整您的查询会更好,以便它们遵守ONLY_FULL_GROUP_BY 规则。使用MINMAX 肯定可以用于这样做。

【讨论】:

感谢您的宝贵时间和回复,由 wat 提供,ANY_VALUE 参考 dev.mysql.com/doc/refman/5.7/en/… 在我的情况下,使用 MAX 而不是 ANY_VALUE 允许我的查询同时适用于 MySQL 5.5。和 5.7。感谢您的建议。 感谢您提出MAX 方法。我的用例完全有意义,它甚至使生成的查询更好【参考方案3】:

几十年来,您可以编写在标准 SQL 中无效但在 mysql 中完全有效的查询

在标准 SQL 中,包含 GROUP BY 子句的查询不能引用 到选择列表中未在 GROUP BY 子句。例如,此查询在标准 SQL 中是非法的 因为选择列表中的非聚合名称列没有 出现在 GROUP BY 中:

SELECT o.custid, c.name, MAX(o.payment) FROM orders AS o, customers AS c WHERE o.custid = c.custid GROUP BY o.custid;对于查询 是合法的,名称列必须从选择列表中省略或 在 GROUP BY 子句中命名。

MySQL 扩展了 GROUP BY 的标准 SQL 用法,以便选择列表 可以引用未在 GROUP BY 子句中命名的非聚合列。

这来自GROUP BY 上的 Mysql 5.6 手册页。如果您查看5.7.6 的同一页面,您会发现情况发生了变化。并且发生了巨大的变化!

该页面还为您提供了解决方案。禁用 ONLY_FULL_GROUP_BY 这将使您的旧 5.6 查询可以在 5.7.6 上工作(从您的查询中删除 ANY_VALUE,因为它在 5.7.6 中不可用,但请改用 ONLY_FULL_GROUP_BY)。

【讨论】:

感谢您的宝贵时间和回复。

以上是关于mysql 5.6 是不是有 ANY_VALUE 功能?的主要内容,如果未能解决你的问题,请参考以下文章

使用 brew mysql.server 安装 mysql@5.6 不是命令

创建新的 AWS RDS 实例并导入数据,而不是将 MySQL 版本从 5.6 更新到 5.7

MariaDB 10.0 和 MySQL 5.6 有何不同

[MySQL 5.6] 初识5.6的optimizer trace

安装MYSQL 5.6

Mysql 5.6 新特性(转载)