mysql 5.6 有 ANY_VALUE 功能吗?

Is there ANY_VALUE capability for mysql 5.6?

目前我正在使用 mysql 5.7 开发和 5.6 生产。每次我 运行 在开发中使用 group by 进行查询时,我都会收到一些错误,例如 "Error Code: 1055. Expression #1 of SELECT list is not in 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 聚合函数代替 ANY_VALUE

或者,您可以考虑不设置 ONLY_FULL_GROUP_BY SQL 模式,这是 MySql 5.7 的默认设置,它是造成您与 [=25] 体验的差异的原因=] 5.6。然后您可以延迟查询的更新,直到您将所有环境迁移到 MySql 5.7.

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

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

的查询

In standard SQL, a query that includes a GROUP BY clause cannot refer to nonaggregated columns in the select list that are not named in the GROUP BY clause. For example, this query is illegal in standard SQL because the nonaggregated name column in the select list does not appear in the 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; For the query to be legal, the name column must be omitted from the select list or named in the GROUP BY clause.

MySQL extends the standard SQL use of GROUP BY so that the select list can refer to nonaggregated columns not named in the GROUP BY clause.

这来自 GROUP BY. If you look at the same page for 5.7.6 上的 Mysql 5.6 手册页,您会发现情况有所改变。并且发生了翻天覆地的变化!!

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

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

在生产中,您可以关闭 ONLY_FULL_GROUP_BY MySQL Mode. Try doing this:

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

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

但是你看,你的查询并不完全正确。当您可以说服它 运行 时,它 return 是 images table 中随机选择的行。这种不确定性通常会给用户和您的技术支持人员带来困惑。

为什么不让查询更好,所以它选择了特定的图像。如果您的 images table 有一个自动增量 id 列,您可以对 select "first" 图像执行此操作。

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

这将 return 每个国家/地区一行,并显示谓词 table 图像。