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

Har*_*tty 37 mysql sql

我有一个emp包含以下结构和数据的表:

name   dept    salary
-----  -----   -----
Jack   a       2
Jill   a       1
Tom    b       2
Fred   b       1
Run Code Online (Sandbox Code Playgroud)

当我执行以下SQL时:

SELECT * FROM emp GROUP BY dept
Run Code Online (Sandbox Code Playgroud)

我得到以下结果:

name   dept    salary
-----  -----   -----
Jill   a       1
Fred   b       1
Run Code Online (Sandbox Code Playgroud)

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

我在MySQL中运行此查询.

注1:我知道查询本身没有意义.我试图用'GROUP BY'方案调试问题.我试图理解为此目的的默认行为.

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

SELECT A.*, MIN(A.salary) AS min_salary FROM emp AS A GROUP BY A.dept
Run Code Online (Sandbox Code Playgroud)

我没有找到任何描述这种SQL工作原理的材料,更重要的是如果我能够始终如一地依赖这种行为.如果这是一个可靠的行为,那么我可以避免以下查询:

SELECT A.* FROM emp AS A WHERE A.salary = ( 
            SELECT MAX(B.salary) FROM emp B WHERE B.dept = A.dept)
Run Code Online (Sandbox Code Playgroud)

mjv*_*mjv 36

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

简而言之,出于性能目的,MySQL允许省略GROUP BY中的某些列,但是只有当省略的列都具有相同的值(在分组中)时,这才有效,否则,查询返回的值确实是不确定的,如在这篇文章中被其他人恰当地猜到了.确保添加ORDER BY子句不会重新引入任何形式的确定性行为.

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

摘自MySQL 5.0文档:

When using this feature, all rows in each group should have the same values
for the columns that are omitted from the GROUP BY part. The server is free
to return any value from the group, so the results are indeterminate unless
all values are the same. 


小智 10

这有点晚了,但我会把它放在以后参考.

GROUP BY获取具有重复的第一行,并丢弃在结果集中匹配的任何行.因此,如果Jack和Tom拥有相同的部门,那么在普通SELECT中首先出现的人将成为GROUP BY中的结果行.

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

SELECT * FROM (SELECT * FROM emp ORDER BY name) as foo GROUP BY dept
Run Code Online (Sandbox Code Playgroud)

这是我发现的最佳表现技术.我希望这可以帮助别人.

  • 我找不到任何引用支持你的断言"GROUP BY占用第一行有重复并丢弃在结果集中匹配的任何行."相反,MySQL特别清楚地说明了非聚合列的值从组中的任何一行任意取. (6认同)
  • 这不是**帮助.我认为这种情况正在恶化.如果是一个非标准功能,您现在使用两个非标准功能.结果可能是错误的,并且无法保证您将获得每个部门的第一个结果,按名称排序. (2认同)
  • **小心**这个答案是**不正确**。看起来它应该可以工作,如果它有效,那就太好了,但它不起作用...... (2认同)