MySQL分组查询报错及需求实现:查找各产品最低价区域
解决MySQL GROUP BY报错及产品最低价格区域查询问题
首先,咱们先搞定你遇到的报错问题:你看到的ER_WRONG_FIELD_WITH_GROUP错误,是因为MySQL开启了only_full_group_by模式——这个模式要求SELECT列表里的非聚合列必须全部出现在GROUP BY子句中,而你的原查询里product.name和price.price都不在GROUP BY里,自然触发了错误。更关键的是,原查询的逻辑也偏离了需求:你要的是按产品分组找最低价格的区域,不是按区域分组。
接下来直接给你符合需求的查询方案,这里推荐用窗口函数(MySQL 8.0及以上支持),逻辑清晰易懂:
SELECT product.name AS product, region.name AS region, price.price FROM ( SELECT price.productId, price.regionId, price.price, -- 按产品分组,先按价格升序(找最低),再按区域名升序(价格相同选字母靠前的) ROW_NUMBER() OVER ( PARTITION BY price.productId ORDER BY price.price ASC, region.name ASC ) AS row_rank FROM price JOIN region ON region.id = price.regionId ) AS ranked_prices JOIN product ON product.id = ranked_prices.productId JOIN region ON region.id = ranked_prices.regionId -- 只保留每个产品的第一条记录(即最低价格+字母最靠前的区域) WHERE ranked_prices.row_rank = 1;
代码解释:
- 子查询
ranked_prices里,用ROW_NUMBER()窗口函数给每个产品的所有价格记录排序:PARTITION BY price.productId:按产品ID分组,确保每个产品单独排序ORDER BY price.price ASC, region.name ASC:先按价格从小到大排(锁定最低价格),如果价格相同,就按区域名称的字母顺序从小到大排
- 外层查询筛选出每个组里排名为1的记录,就是每个产品符合要求的结果。
如果你的MySQL版本低于8.0,不支持窗口函数,可以用关联子查询的方式实现:
SELECT p.name AS product, r.name AS region, pr.price FROM price pr JOIN product p ON p.id = pr.productId JOIN region r ON r.id = pr.regionId WHERE (pr.productId, pr.price, r.name) IN ( SELECT productId, MIN(price) AS min_price, -- 当多个区域价格同为最低时,取字母最靠前的区域名 MIN(r.name) AS top_region FROM price JOIN region r ON r.id = price.regionId GROUP BY productId );
验证结果:
执行上面的查询后,会得到你期望的结果:
| product | region | price |
|---|---|---|
| Crab | Kharkov | 100.00 |
| Crayfish | Kharkov | 100.00 |
内容的提问来源于stack exchange,提问作者kolya kolya
相关产品推荐
相关产品推荐

