我有一张名为child
的表格,如此
+---------+-----+
| name | age |
+---------+-----+
| Alfred | 5 |
| Maria | 6 |
+---------+-----+
当我运行SELECT 'name' FROM 'child'
时,我得到两行。没问题。这是我的预期。
但如果我跑SELECT 'name', MAX('age') FROM 'child'
,我得到:
+---------+------------+
| name | MAX(`age`) |
+---------+------------+
| Alfredo | 6 |
+---------+------------+
这个结果对我来说是一个额外的..我期待两行像以前一样,为什么它只输出一行?为什么Alfredo
输出,因为玛丽亚是谁6岁?我在哪里可以找到关于此行为的文档?
答案 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是如何解决这个问题的一些例子。
为安全起见,您可以通过设置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
子句中出现的表达式将被独立评估。 name
和MAX(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(*)
不是年龄或名字,只是一个数字。将它与您存储在表中的值进行比较没有任何意义。