MySQL GROUP BY取MIN(price)时关联tokenId错误的解决方法
解决分组后获取每组最低价对应完整行的问题
你当前的SQL写法存在逻辑问题:当使用GROUP BY resourceGroupId时,只有分组列(resourceGroupId)和聚合函数计算的列(比如MIN(price))是确定的。像tokenId这种既不在分组列里、也不是聚合结果的字段,数据库会从分组内的任意一行取对应值返回,这就是为什么你得到的tokenId和最低价不匹配。
下面提供几种可行的解决方案:
方法1:窗口函数(推荐,适用于MySQL 8.0+、PostgreSQL、SQL Server等)
通过窗口函数给每行标记所在分组内的价格排名,再筛选出排名第一的行:
SELECT resourceGroupId, price, tokenId FROM ( SELECT resourceGroupId, price, tokenId, -- 按resourceGroupId分组,每组内按price升序排名 ROW_NUMBER() OVER (PARTITION BY resourceGroupId ORDER BY price ASC) AS rn FROM market_listing ) t WHERE rn = 1;
如果同一分组内有多个相同最低价的行,ROW_NUMBER()会随机保留一行;若想保留所有最低价的行,将ROW_NUMBER()替换为RANK()或DENSE_RANK()即可。
方法2:子查询关联
先查询每个分组的最低价格,再和原表关联获取对应行数据:
SELECT ml.resourceGroupId, ml.price, ml.tokenId FROM market_listing ml JOIN ( -- 先得到每个resourceGroupId的最低价格 SELECT resourceGroupId, MIN(price) AS min_price FROM market_listing GROUP BY resourceGroupId ) t ON ml.resourceGroupId = t.resourceGroupId AND ml.price = t.min_price;
这种写法会返回同一分组内所有价格等于最低价的行。
方法3:MySQL 5.x 兼容写法(无窗口函数支持时)
利用NOT EXISTS筛选出分组内没有更低价格的行:
SELECT resourceGroupId, price, tokenId FROM market_listing ml WHERE NOT EXISTS ( SELECT 1 FROM market_listing ml2 WHERE ml2.resourceGroupId = ml.resourceGroupId AND ml2.price < ml.price );
此方法同样会返回分组内所有最低价的行。
内容的提问来源于stack exchange,提问作者gabriel mellace
相关产品推荐
相关产品推荐

