MySQL:使用SELECT和MAX的新手

时间:2015-01-26 17:34:19

标签: mysql

我有一张名为child的表格,如此

+---------+-----+
| name    | age |
+---------+-----+
| Alfred  |   5 |
| Maria   |   6 |
+---------+-----+

当我运行SELECT 'name' FROM 'child'时,我得到两行。没问题。这是我的预期。

但如果我跑SELECT 'name', MAX('age') FROM 'child',我得到:

+---------+------------+
| name    | MAX(`age`) |
+---------+------------+
| Alfredo |          6 |
+---------+------------+

这个结果对我来说是一个额外的..我期待两行像以前一样,为什么它只输出一行?为什么Alfredo输出,因为玛丽亚是谁6岁?我在哪里可以找到关于此行为的文档

4 个答案:

答案 0 :(得分:1)

您需要使用GROUP BY来获取多行。否则,聚合函数MAX()将应用于所有行。请注意,Alfredo的年龄实际上是5.在这种情况下,名称是组。

MySQL在这方面很特别,因为它不遵循ANSI标准SQL。当你没有在select子句中指定group by子句中的列或在其上应用聚合函数时,通常会引发错误。 MySQL允许这样做(这将在未来版本中更改,顺便说一句)并在此组中显示随机行。所以不要这样做。

要在示例中获得两行,您必须执行

SELECT name, MAX(age) FROM your_table GROUP BY name;

每个名字都是"组"。如果你的桌子上有另一个25岁的Alfredo,结果将是Alfredo - 25和Maria - 6.

当你想获得属于group-wise最大值的行时,它会比这更复杂。 Here是如何解决这个问题的一些例子。

More info to read

为安全起见,您可以通过设置sql_mode only_full_group_by来禁用此功能。如果您没有权利,请询问您的管理员。

答案 1 :(得分:0)

SQL聚合函数的使用应该伴随GROUP BY子句。这是一个很好的起点:https://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html

答案 2 :(得分:0)

您应该仅使用sql语句将SQL聚合为Average,Max等函数。否则你会得到像这样的未定义行为。

这里如果你只写max(age),一切看起来都很好,你得到6,但现在你也要求它打印名称(没有条件,即要求它打印所有名字,而最大只会是一个行),所以它试图做一些聪明的事情,打印第一行就是你的情况。

答案 3 :(得分:0)

MAX()是与GROUP BY一起使用的aggregate function。如果缺少GROUP BY子句,则任何RDBMS将从所有选定的行生成一个组,并且它将返回单行。

当涉及分组时,SELECT子句中出现的表达式将被独立评估。 nameMAX(age)之间没有任何关系。 MAX(age)age子句筛选的行(您的案例中的所有行)中列WHERE的最大值。

标准SQL语言不允许SELECT不依赖于GROUP BY列或在聚合函数中使用的列。
MySQL允许这个before version 5.7.5。从版本5.7.5开始,它遵循标准并拒绝这些有错误的查询。使用配置仍然可以实现旧的行为。

正如文档中所述,SELECT列既不依赖于GROUP BY列,也不用于聚合函数,"the server is free to choose any value from each group"。这是未定义的行为

返回查询:

SELECT 'name', MAX('age') FROM 'child'

没有WHERE包含所有行。然后,由于MAX(age)(这是一个聚合函数),MySQL创建一个包含所有已过滤行(所有行)的组,并评估SELECT子句中的每个表达式。

MAX(age)非常清楚,它评估的是组中行的age列的最大值。那是6,仅此而已。不保留对其中提取的行的引用。

选择name受上面公开的未定义行为的影响。服务器将选择任何值,这次,似乎首选从第一行中选择值。它可能在另一台服务器上有所不同。添加,删除或更新该表上的行后,在同一服务器上可能会有所不同。它无法预测。

为什么会出现这种情况?

为什么服务器无法从同一行获取值MAX(age)?难道难以实现吗? - 这是许多初学者在开始使用SQL时的想法。

简短的回答是:因为没有这样的行

我们要说SQL应从所选的同一行name中选择MAX('age')
让我们在查询中添加更多aggregate functions

SELECT 'name', MAX('age'), MIN('age'), AVG('age'), COUNT(*) FROM 'child'

如果上述断言是正确的,SQL应该从包含name(第2行)的同一行获得MAX(age)。如果有两行包含该值会怎样?

但是,同时它应该从包含name的同一行获得MIN(age)(嗯,这是第1行)。

或者,它应该从找到AVG(age)的行(5.5获取它; oops,没有这样的行。)

列中包含COUNT(*)的行...错误...在哪个列中应检查COUNT(*)?顺便说一下,COUNT(*)不是年龄或名字,只是一个数字。将它与您存储在表中的值进行比较没有任何意义。