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

使用MySQL聚合函数MIN时获取正确的行数据?,mysql,sql,aggregate-functions,min,Mysql,Sql,Aggregate Functions,Min,现在,据我所知,当您使用聚合函数(如AVG、SUM等)时,您必须记住,您选择的任何其他字段(不包括在聚合函数中)都是不确定的,例如: SELECT AVG(amount), name, desc FROM some_table; SELECT MIN(media_id), auction_id, media_url FROM auction_media WHERE auction_id IN( 119925, 124660, 124663, 129078,

现在,据我所知,当您使用聚合函数(如
AVG
SUM
等)时,您必须记住,您选择的任何其他字段(不包括在聚合函数中)都是不确定的,例如:

SELECT AVG(amount), name, desc FROM some_table;
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;
我理解这一点,这是因为来自聚合函数的值没有绑定到任何一行,因此选择的其他字段是不确定的

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

例如:

SELECT AVG(amount), name, desc FROM some_table;
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;
如果我的想法是正确的,那么这将始终返回正确的
媒体url
对吗

但是,如果使用不同类型的聚合函数,如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;
如果查询作者知道未聚合字段是,则可以通过分组而不是聚合值来确定

但是,如果使用不同类型的聚合函数,如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;

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

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

如果我的想法是正确的,那么它将始终返回正确的媒体url,对吗

否。如果您的数据是:

auction\u id media\u id media\u url
119925       3          http://google.com
119925       5          http://yahoo.com
119925       3          http://bing.com
您的查询
SELECT MIN(media\u id)、auction\u id、media\u url GROUP BY auction\u id
将返回
MIN(media\u id)
3
,以及
auction\u id
119925
,但它会返回什么
media\u url

media\u url
仍不确定

你看,数据中没有任何内容表明
media\u url
media\u id
有任何关系


您可能(认为您)知道,对于特定的
媒体id
,非规范化的
媒体url
始终是相同的,但这对SQL引擎来说并不重要。

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

如果我的想法是正确的,那么它将始终返回正确的媒体url,对吗

否。如果您的数据是:

auction\u id media\u id media\u url
119925       3          http://google.com
119925       5          http://yahoo.com
119925       3          http://bing.com
您的查询
SELECT MIN(media\u id)、auction\u id、media\u url GROUP BY auction\u id
将返回
MIN(media\u id)
3
,以及
auction\u id
119925
,但它会返回什么
media\u url

media\u url
仍不确定

你看,数据中没有任何内容表明
media\u url
media\u id
有任何关系


您可能(认为您)知道,对于特定的
媒体id
,非规范化的
媒体url
总是相同的,但这对SQL引擎来说并不重要。

否。聚合查询中未聚合的列(不在
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\u媒体(auction\u id,media\u type,upload\u progress,media\u id)
auction\u媒体(media\u type,upload\u progress,auction\u id)
否上建立索引。聚合查询中未聚合的列(不在
group by
中)来自任意不确定的行。这种笨拙的行为是大多数数据库中不允许使用语法的原因,也是MySQL最新版本默认情况下“关闭”语法的原因。因此,您的查询将返回一个错误

这里有一种方法可以做你想做的事