使用MySQL聚合函数MIN时获取正确的行数据? [重复]

问题描述 投票:0回答:3

现在,据我了解,当您使用聚合函数(例如

AVG
SUM
等)时,您必须记住,您
SELECT
未参与聚合函数的任何其他字段将是不确定的,因为示例:

SELECT AVG(amount), name, desc FROM some_table;

我理解这一点,这是因为来自聚合函数的值不依赖于任何一行,因此选择的其他字段是不确定的。

但是,如果您使用不同类型的聚合函数,例如

MIN
MAX
,其中它们检索的内容 is 绑定到特定行,那么可以安全地假设选择的任何其他字段不在某个行中聚合函数可以确定吗? ...结果与特定的数据行相关联,与其他聚合函数结果不同?

例如:

SELECT MIN(media_id),
       auction_id,
       media_url
FROM   auction_media
WHERE  auction_id IN( 119925, 124660, 124663, 129078,
                      129094, 134395, 149753, 152221,
                      154733, 154737, 154742, 157694,
                      161411, 165965, 165973 )
       AND media_type = 1
       AND upload_in_progress = 0
GROUP  BY auction_id;

如果我的想法是正确的,这将总是返回正确的

media_url
,对吗?

mysql sql aggregate-functions min
3个回答
2
投票

但是,如果您使用不同类型的聚合函数,例如 MIN 或 MAX,他们检索的内容与某一行相关联,那么是吗? 可以安全地假设选择的任何其他字段不在 可以确定聚合函数吗?

不。其一,多行可以有最小值或最大值;另一方面,没有什么可以阻止查询同时选择 MIN(a)、MAX(a)、AVG(a) 和 SUM(a)(我非常怀疑 MySQL 会使其查询引擎过于复杂化以利用它“如果查询只有一个聚合......”)


注意:我相当确定 MySQL 最初允许此类查询的唯一原因是在以下情况下进行速记:

SELECT a.*, SUM(b.X)
FROM a INNER JOIN b ON a.PK = b.a_PK
GROUP BY a.PK;

查询作者知道非聚合字段可以通过分组来确定,而不是聚合值。


2
投票

MIN
MAX
AVG
SUM
相比,不再与任何行相关联。所有 4 个都是聚合多个行的结果,无论是所有行(如您的第一个查询),还是组中的行(如您的第二个查询)。

如果我的想法是正确的,这总是会返回正确的 media_url 对吗?

不。如果您的数据是:

auction_id   media_id   media_url
119925       3          http://google.com
119925       5          http://yahoo.com
119925       3          http://bing.com

您的查询

SELECT MIN(media_id), auction_id, media_url GROUP BY auction_id
将为
3
返回
MIN(media_id)
,为
119925
返回
auction_id
,但它会返回什么
media_url

media_url
仍不确定。

您看,数据中没有任何内容表明

media_url
media_id
有任何关系。

可能(认为您)知道非规范化的

media_url
对于特定的
media_id
始终是相同的,但这对SQL引擎来说并不重要。


2
投票

不。聚合查询中的未聚合列(不在

group by
中)来自任意不确定行。这种尴尬的行为是大多数数据库不允许使用该语法的原因,也是 MySQL 最新版本默认“关闭”该语法的原因。因此您的查询将返回错误。

这是做你想做的事情的一种方法:

SELECT am.*
FROM auction_media am
WHERE auction_id IN (119925, 124660, 124663, 129078,
                      129094, 134395, 149753, 152221,
                      154733, 154737, 154742, 157694,
                      161411, 165965, 165973 ) AND
      media_type = 1 AND upload_in_progress = 0 AND
      media_id = (SELECT MIN(am2.media_id)
                  FROM auction_media m2
                  WHERE m2.auction_id = m.auction_id AND m2.media_type = m.media_type AND m2.upload_in_progress = m.upload_in_progress
                 );

为了提高性能,您需要在

auction_media(auction_id, media_type, upload_in_progress, media_id)
auction_media(media_type, upload_in_progress, auction_id)
上建立索引。

© www.soinside.com 2019 - 2024. All rights reserved.