2011-09-04 113 views
8

在以下示例中,为什么min()查询返回结果,但max()查询不?MySQL聚合函数问题

mysql> create table t(id int, a int); 
Query OK, 0 rows affected (0.10 sec) 

mysql> insert into t(id, a) values(1, 1); 
Query OK, 1 row affected (0.03 sec) 

mysql> insert into t(id, a) values(1, 2); 
Query OK, 1 row affected (0.02 sec) 

mysql> select * from t 
    -> ; 
+------+------+ 
| id | a | 
+------+------+ 
| 1 | 1 | 
| 1 | 2 | 
+------+------+ 
2 rows in set (0.00 sec) 

mysql> select * from t where a < 4; 
+------+------+ 
| id | a | 
+------+------+ 
| 1 | 1 | 
| 1 | 2 | 
+------+------+ 
2 rows in set (0.00 sec) 

mysql> select * from t where a < 4 having a = max(a); 
Empty set (0.00 sec) 

mysql> select * from t where a < 4 having a = min(a); 
+------+------+ 
| id | a | 
+------+------+ 
| 1 | 1 | 
+------+------+ 
1 row in set (0.00 sec) 
+2

该查询在所有其他RDBMS中当然无效。你期望它返回什么? –

回答

7

HAVING子句用于过滤行的组。您参考min(a)max(a)哪些(在没有任何GROUP BY条款的情况下)在表中的所有a值上聚合,但是随后使用与单个a值的比较。

那么MySQL应该使用哪个值a?我知道的所有其他RDBMS在这一点上都会引发错误,但是MySQL确实允许这样做。 From the docs

标准SQL不允许HAVING子句来命名GROUP BY子句中没有发现,除非它被封装在一个聚合 功能的任何列 。 MySQL允许使用这样的列来简化 的计算。此扩展假设非分组列将 具有相同的分组值。 否则,结果是 不确定。

所以你的情况从你所得到的结果看来,它结束了使用1a标值,但这种行为并不能完全保证其可以等效地使用2或任何其他现有a值。

+0

为了证明结果的不确定性,可以添加一个'a = 0'的行。现在你的语句都不会返回任何行。 – NullUserException

+2

正确的做法是使用子查询:'select * from t where a =(select min(a)from t);' – NullUserException