通过按主键对分组进行选择的结果对MySQL进行分组,未排序的子查询结果

时间:2018-08-20 15:14:06

标签: mysql group-by mysql-5.7

在我的一个旧版应用程序中,有一个查询来获取每个组的第一行,即

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}}。

谁能指出为什么第一个查询没有按预期运行?

3 个答案:

答案 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