2012-08-15 172 views
1

考虑这两个查询:为什么在还为列返回MAX值时始终返回最低ID行?

SELECT *, MAX(age) AS maxAge FROM someTable ORDER BY age ASC; 
SELECT *, 'dummyC' AS dummyC FROM someTable ORDER BY age ASC; 

前者查询返回的所有行和表的所有列,加上额外的虚拟列。后面的查询只返回一行,即具有最低主键的那一行。为什么是这样,我该如何解决它?在一些旧的但稳定的Debian服务器上测试MySQL 5.1。

+1

难道你没有'前'和'后者'颠倒吗? – tdammers 2012-08-15 21:49:51

回答

3

这是一个MySQL extension一样,这是有用的。

MySQL扩展了GROUP BY的用法,以便选择列表可以引用未在GROUP BY子句中指定的非聚合列。这意味着前面的查询在MySQL中是合法的。您可以使用此功能通过避免不必要的列排序和分组来获得更好的性能。但是,这非常有用,因为每个未在GROUP BY中命名的非聚合列中的所有值对于每个组都是相同的。服务器可以自由选择每个组中的任何值,因此除非它们相同,否则所选值是不确定的。此外,每个组的值的选择不能通过添加ORDER BY子句来影响。结果集的排序在选择值后发生,而ORDER BY不影响服务器选择的值。

您得到的值是不确定的。您经常会得到插入表中的第一行,但这不能保证。

如果你想从该行包含的最高年龄那么最好是使用的ORDER BYLIMIT 1组合对应的值:

SELECT * 
FROM someTable 
ORDER BY age DESC 
LIMIT 1; 
+0

谢谢马克。假设我需要包含最低年龄的行中的值,但也需要最高年龄的值,那么我将如何获得该信息是单个查询? [我问这是一个单独的问题](http://stackoverflow.com/questions/11982629/how-to-query-row-with-lowest-value-and-also-to-know-the-value-of -the-最高-VA)。 – dotancohen 2012-08-16 07:37:07

1

在第一个查询中,*是hidden columns

引述MySQL文档:

MySQL的扩展使用GROUP BY的,这样的选择列表可参考 在GROUP BY子句中未命名的非聚合列。这意味着 前面的查询在MySQL中是合法的。您可以使用此功能 以避免不必要的列排序和 分组以获得更好的性能。然而,当主要在GROUP BY没有命名每个 非聚合列中的所有值对每个 组

2

第一个查询具有聚合函数(MAX),但没有GROUP BY,这意味着它在整个结果集上进行聚合(收集和合并值),并将其作为一行返回。大多数SQL方言不允许非聚合列在这样的查询中出现,但MySQL专门允许它。但是,这些非聚合列由来自MySQL遇到的第一行的值填充,可能是任何行。如果您从来没有从相关表中删除,MySQL通常会首先查找ID最低的行,因为它以与存储在磁盘上相同的顺序扫描表(至少在需要全表扫描时)。如果您要在桌面上运行一堆DELETE和后续的INSERT语句,您至少会在某些查询中获得其他行。总之,不要指望得到任何特定的行。

第二个查询缺少聚集函数,因此它不执行任何隐式分组 - 您只需获取完整的结果集。

相关问题