在SELECT子句中没有聚合函数时GROUP BY行为

我有一个表emp与以下结构和数据:

 name dept salary ----- ----- ----- Jack a 2 Jill a 1 Tom b 2 Fred b 1 

当我执行下面的SQL时:

 SELECT * FROM emp GROUP BY dept 

我得到以下结果:

 name dept salary ----- ----- ----- Jill a 1 Fred b 1 

服务器在什么基础上决定返回吉尔和弗雷德,排除杰克和汤姆?

我在MySQL中运行这个查询。

注1:我知道这个查询没有意义。 我试图用“GROUP BY”schemedebugging一个问题。 我想了解为此目的的默认行为。

注2:我习惯编写与GROUP BY子句相同的SELECT子句(减去聚合字段)。 当我遇到上面描述的行为时,我开始想知道是否可以依赖于这种情况,例如:从emp表中select行中薪水最低/最高的那些行。 例如:像这样的SQL语句适用于MySQL:

 SELECT A.*, MIN(A.salary) AS min_salary FROM emp AS A GROUP BY A.dept 

我没有find任何材料来描述为什么这样的SQL工作,更重要的是,如果我可以一直依靠这样的行为。 如果这是一个可靠的行为,那么我可以避免像这样的查询:

 SELECT A.* FROM emp AS A WHERE A.salary = ( SELECT MAX(B.salary) FROM emp B WHERE B.dept = A.dept) 

阅读关于这个特定点的MySQL文档

简而言之,为了提高性能,MySQL允许省略GROUP BY中的某些列,但只有在省略的列都具有相同的值 (分组内)的情况下,MySQL 才会有效 ,否则查询返回的值确实是不确定的 。在这篇文章中被别人正确地猜到了。 为了确保添加ORDER BY子句不会重新引入任何forms的确定性行为。

虽然这不是问题的核心,但是这个例子显示了如何使用*而不是明确地列举所需的列通常是一个坏主意。

摘自MySQL 5.0文档:

使用此function时,每个组中的所有行应具有相同的值
用于从GROUP BY部分省略的列。 服务器是免费的
从组中返回任何值,所以结果是不确定的,除非
所有的值都是一样的。 

这有点晚了,但我会把这个提供给未来的参考。

GROUP BY采用具有重复的第一行,并放弃结果集中所有匹配的行。 因此,如果Jack和Tom拥有相同的部门,则在正常SELECT中出现的人将成为GROUP BY中的结果行。

如果要控制列表中第一个出现的内容,则需要执行ORDER BY。 但是,SQL不允许ORDER BY在GROUP BY之前,因为它会引发exception。 解决此问题的最佳解决方法是在子查询中执行ORDER BY,然后在外部查询中执行GROUP BY。 这是一个例子:

 SELECT * FROM (SELECT * FROM emp ORDER BY name) as foo GROUP BY dept 

这是我find的performance最好的技术。 我希望这可以帮助别人。

据我所知,为了您的目的,返回的特定行可以被随意地简化。

sorting只在GROUP BY完成后进行

你可以把一个:

SET sql_mode ='ONLY_FULL_GROUP_BY'

在查询之前执行SQL标准的GROUP BY行为

我发现最好的办法是考虑这种types的查询不受支持。 在大多数其他数据库系统中,不能包含不在GROUP BY子句中的列或在HAVING,SELECT或ORDER BY子句中的聚合函数中。

相反,请考虑您的查询读取:

 SELECT ANY(name), dept, ANY(salary) FROM emp GROUP BY dept; 

…因为这是怎么回事

希望这可以帮助….

我认为ANSI SQL要求select只包含来自GROUP BY子句的字段以及聚合函数。 MySQL的这种行为看起来像返回一些行,可能是服务器读取的最后一行,或者它手边的任何行,但不依赖于这一行。

尝试使用ORDER BY来select你想要的行。

 SELECT * FROM emp GROUP BY dept ORDER BY name ASC; 

将返回以下内容:

 name dept salary ----- ----- ----- jack a 2 fred b 1 

如果按部门分组,对其他数据是否有影响? 我知道Sql Server甚至不会允许这个查询。 如果有可能这听起来像可能有其他问题。