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

时间:2018-04-09 20:13:27

标签: mysql sql aggregate-functions min

现在,正如我所知,当你使用AVGSUM之类的聚合函数时,你必须记住,你SELECT的任何其他字段也不是参与聚合函数将是不确定的,例如:

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

我理解这一点,这是因为来自聚合函数的值并不与任何一行相关联,因此所选的其他字段是不确定的。

但是,如果您使用其他类型的聚合函数,例如MINMAX,那么它们检索的 绑定到某一行,那么可以安全地假设是否可以确定在聚合函数中选择的任何其他字段 ? ...结果绑定到特定的数据行,这与其他聚合函数结果不同?

例如:

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权利吗?

3 个答案:

答案 0 :(得分: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;

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

答案 1 :(得分:2)

MINMAX不再绑定到AVGSUM之外的任何行。所有这四个都是聚合多个行的结果,无论是所有行(如您首先查询)还是组中的行(如第二个查询)。

  

如果我的想法是对的,那么总会返回正确的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_id3返回MIN(media_id)119925返回auction_id,但返回media_url会是什么?

media_url仍然不确定。

您看,数据中没有任何内容表明media_urlmedia_id有任何关联。

可能(想你)知道非规范化media_url对于特定的media_id总是相同的,但这对SQL引擎无关紧要。< / p>

答案 2 :(得分:2)

没有。聚合查询中的未聚合列(不在group by中)来自任意不确定行。这种尴尬的行为是大多数数据库中不允许使用语法的原因,也是为什么最新版本的MySQL&#34;关闭它&#34;默认情况下。所以你的查询会返回一个错误。

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

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)上的索引。