在我的一个旧版应用程序中,有一个查询来获取每个组的第一行,即
SELECT
columnPrimaryKey,
column1,
column2,
column3,
column4
FROM
(SELECT
columnPrimaryKey,
column1,
column2,
column3,
column4
FROM tableName
ORDER BY column4
) AS tbl
GROUP BY column3
上面的查询没有返回第一行(按column4排序),而是由主键列即columnPrimaryKey
返回第一行。
这曾经可以工作。我记得我们进行了mysql升级,当前版本为5.7.22-log
。
我可以按以下方式重写查询,该查询将按预期工作:
SELECT
x.columnPrimaryKey,
x.column1,
x.column2,
x.column3,
x.column4
FROM tableName AS x INNER JOIN (
SELECT
MIN( column4 ) AS column4,
column3
FROM tableName
GROUP BY column3
) AS y ON x.column4 = y.column4 AND x.column3 = y.column3;
我已经检查了sql_mode
的{{1}}。
谁能指出为什么第一个查询没有按预期运行?
答案 0 :(得分:0)
第一个查询的选择列表:
SELECT
columnPrimaryKey,
column1,
column2,
column3,
column4
尚不清楚,因为您正在以GROUP BY
分组的column3
聚合模式下运行查询。这意味着对于column3
的每个值,只会报告一条记录。如果给定值column3
有多个记录,则您没有告诉MySQL 您要为其他列报告的值。因此,原则上,MySQL可以自由选择它想要的任何值。到底为什么会这样并不重要,以至于您继续使用第二种正确的方法前进。
因此,通常应记住,当按一个或多个列分组时,您只能选择出现在GROUP BY
,或任何其他列中的列,只要它出现在 aggregate 函数中即可。
答案 1 :(得分:0)
此行为是预期的。特别是如果您已从<= 5.7.5升级。 MySQL默认将“ 仅完整分组依据”模式打开。 SideNote:
始终建议在升级到较新版本之前检查其“更改列表”。
MySQL说。
ONLY_FULL_GROUP_BY
拒绝选择列表,具有HAVING条件或ORDER的查询 BY列表是指未在列中未命名的非聚合列 GROUP BY子句也不在功能上依赖于(唯一确定 by)GROUP BY列。
更多在这里。
https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_only_full_group_by
答案 2 :(得分:0)
评论太长,请在此处添加以供参考:
从MySQL文档开始:
MySQL 5.7.5及更高版本实现对功能依赖性的检测。如果 启用了ONLY_FULL_GROUP_BY SQL模式(默认情况下), MySQL拒绝选择列表,具有HAVING条件或 ORDER BY列表引用未在其中命名的非聚合列 GROUP BY子句在功能上也不依赖于它们。 (之前 5.7.5,MySQL不检测功能依赖性,默认情况下未启用ONLY_FULL_GROUP_BY。 )
如果仅禁用ONLY_FULL_GROUP_BY,则为标准的MySQL扩展 SQL对GROUP BY的使用允许选择列表,HAVING条件或 ORDER BY列表引用非聚集列,即使这些列 在功能上不依赖于GROUP BY列。这导致MySQL 接受前面的查询。在这种情况下,服务器可以自由 从每个组中选择任何值,因此,除非它们相同,否则 选择的值是不确定的,这可能不是您所确定的 想。此外,不能从每个组中选择值 受添加ORDER BY子句影响。结果集排序发生 选择值后,并且ORDER BY不会影响哪个 服务器选择的每个组中的值。禁用 由于某些原因,主要是在您了解ONLY_FULL_GROUP_BY时才有用 数据的属性,每个非聚合列中的所有值均不 GROUP BY中命名的每个组都相同。
更多信息可以在这里找到:cascadeValidate
mapping option was added