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 仅当出现以下任一情况时:

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);