SQL MAX() 是如何工作的?
How does SQL MAX() works?
SQL MAX 应该很容易理解,但为什么我的这个查询没有按预期工作?
这是模式和数据
CREATE TABLE orders(
id INT,
name TEXT,
quantity INT,
PRIMARY KEY (id)
);
INSERT INTO orders VALUES
(1, 'abc', 10),
(2, 'def', 3),
(3, 'abc', 2),
(4, 'ghi', 4),
(5, 'ghi', 7),
(6, 'ghi', 13);
这是查询
select t.name, max(t.avgq) from (
select name, avg(quantity) as avgq
from orders group by name
) as t;
我从mysql和sqlfiddle得到的结果都是这样
name max(t.avgq)
-----+-------------
abc 8
实际应该在的位置
name max(t.avgq)
-----+--------------
ghi 8
这是为什么?
您使用的查询实际上无效。您应该聚合所有未分组的列。在这种情况下,它适用于 t.name
.
与其他更严格的数据库系统不同,MySQL 允许此查询为 运行 并采用他们遇到的第一个值作为 t.name
字段。当 grouping
或执行计划导致数据集排序不同时,这可能会有所不同。
MAX()
只会 return 该列的最大值,不会影响其他列。要获得您想要的结果,您需要 运行 以下内容:
SELECT name, AVG(quantity) as avgq
FROM orders
GROUP BY name
ORDER BY AVG(quantity) DESC
LIMIT 1;
如果你真的想使用 MAX()
功能,但@Paul 回答更好
select name, avg_quantity
from (
select name, avg(quantity) as avg_quantity from orders group by name
) as avg_table
inner join (
select max(avg_quantity) as avg_quantity
from (
select name, avg(quantity) as avg_quantity from orders group by name) as avg_table
) as max_table USING (avg_quantity);
根据SQL标准,你的外部查询不正确。
因为您使用聚合函数 MAX()
而没有 GROUP BY
子句,隐含的 GROUP BY ()
被假定(根据 SQL99 标准和)MySQL:
If you use a group function in a statement containing no GROUP BY
clause, it is equivalent to grouping on all rows.
(来源:12.18.1 GROUP BY (Aggregate) Functions)
您可以在 SELECT
子句中使用 t.name
仅当出现以下任一情况时:
- 它也出现在
GROUP BY
子句中;
- 它被用作一个参数
GROUP BY
aggregate function;
- functionally dependent 出现在
GROUP BY
子句中的列上。
MySQL 接受 SELECT
字段不遵循上面列举的 GROUP BY
规则的查询,但在这种情况下,为这些字段返回的值是不确定的:
... a MySQL
extension to the use of GROUP BY
is to permit the select list, HAVING
condition, or ORDER BY
list to refer to nonaggregated columns even if the columns are not functionally dependent on GROUP BY
columns. This causes MySQL
to accept the (...) query. In this case, the server is free to choose any value from each group, so unless they are the same, the values chosen are indeterminate, which is probably not what you want.
(来源:12.18.3 MySQL Handling of GROUP BY)
有效的查询
您可以保留内部查询,按 AVG(quantity)
降序排列结果行,并使用 SQL 标准的另一个 MySQL
扩展(即 LIMIT
)来获得只有第一个值(排序后的最大值)。
查询是:
SELECT name, AVG(quantity) AS avgq
FROM orders
GROUP BY name
ORDER BY avgg DESC
LIMIT 1
select t.name, max(t.avgq) from (
select name, avg(quantity) as avgq
from orders group by name
) as t;
如有错误请指正
- 每当我们在 select 查询中使用带有聚合函数的任何列时,该列都应该是 group by 子句的一部分以避免歧义。
所以正确的查询可以是
select t.name , max(t.avgq)from (
select name, avg(quantity) as avgq
from table3 group by name
) as t
group by t.name,t.avgq
having t.avgq =(select max(tq.avgq) from (
select name, avg(quantity) as avgq
from table3 group by name
)tq);
SQL MAX 应该很容易理解,但为什么我的这个查询没有按预期工作?
这是模式和数据
CREATE TABLE orders(
id INT,
name TEXT,
quantity INT,
PRIMARY KEY (id)
);
INSERT INTO orders VALUES
(1, 'abc', 10),
(2, 'def', 3),
(3, 'abc', 2),
(4, 'ghi', 4),
(5, 'ghi', 7),
(6, 'ghi', 13);
这是查询
select t.name, max(t.avgq) from (
select name, avg(quantity) as avgq
from orders group by name
) as t;
我从mysql和sqlfiddle得到的结果都是这样
name max(t.avgq)
-----+-------------
abc 8
实际应该在的位置
name max(t.avgq)
-----+--------------
ghi 8
这是为什么?
您使用的查询实际上无效。您应该聚合所有未分组的列。在这种情况下,它适用于 t.name
.
与其他更严格的数据库系统不同,MySQL 允许此查询为 运行 并采用他们遇到的第一个值作为 t.name
字段。当 grouping
或执行计划导致数据集排序不同时,这可能会有所不同。
MAX()
只会 return 该列的最大值,不会影响其他列。要获得您想要的结果,您需要 运行 以下内容:
SELECT name, AVG(quantity) as avgq
FROM orders
GROUP BY name
ORDER BY AVG(quantity) DESC
LIMIT 1;
如果你真的想使用 MAX()
功能,但@Paul 回答更好
select name, avg_quantity
from (
select name, avg(quantity) as avg_quantity from orders group by name
) as avg_table
inner join (
select max(avg_quantity) as avg_quantity
from (
select name, avg(quantity) as avg_quantity from orders group by name) as avg_table
) as max_table USING (avg_quantity);
根据SQL标准,你的外部查询不正确。
因为您使用聚合函数 MAX()
而没有 GROUP BY
子句,隐含的 GROUP BY ()
被假定(根据 SQL99 标准和)MySQL:
If you use a group function in a statement containing no
GROUP BY
clause, it is equivalent to grouping on all rows.
(来源:12.18.1 GROUP BY (Aggregate) Functions)
您可以在 SELECT
子句中使用 t.name
仅当出现以下任一情况时:
- 它也出现在
GROUP BY
子句中; - 它被用作一个参数
GROUP BY
aggregate function; - functionally dependent 出现在
GROUP BY
子句中的列上。
MySQL 接受 SELECT
字段不遵循上面列举的 GROUP BY
规则的查询,但在这种情况下,为这些字段返回的值是不确定的:
... a
MySQL
extension to the use ofGROUP BY
is to permit the select list,HAVING
condition, orORDER BY
list to refer to nonaggregated columns even if the columns are not functionally dependent onGROUP BY
columns. This causesMySQL
to accept the (...) query. In this case, the server is free to choose any value from each group, so unless they are the same, the values chosen are indeterminate, which is probably not what you want.
(来源:12.18.3 MySQL Handling of GROUP BY)
有效的查询
您可以保留内部查询,按 AVG(quantity)
降序排列结果行,并使用 SQL 标准的另一个 MySQL
扩展(即 LIMIT
)来获得只有第一个值(排序后的最大值)。
查询是:
SELECT name, AVG(quantity) AS avgq
FROM orders
GROUP BY name
ORDER BY avgg DESC
LIMIT 1
select t.name, max(t.avgq) from (
select name, avg(quantity) as avgq
from orders group by name
) as t;
如有错误请指正
- 每当我们在 select 查询中使用带有聚合函数的任何列时,该列都应该是 group by 子句的一部分以避免歧义。
所以正确的查询可以是
select t.name , max(t.avgq)from (
select name, avg(quantity) as avgq
from table3 group by name
) as t
group by t.name,t.avgq
having t.avgq =(select max(tq.avgq) from (
select name, avg(quantity) as avgq
from table3 group by name
)tq);