MySQL GROUP BY获取最高计算分数对应行的最优价格查询问题
解决按客户/客户组优先级获取最优阶梯价格的问题
我懂你现在的困境——你的评分逻辑是对的,但用MAX和GROUP BY的方式没法把最高分和对应的行数据绑定起来,导致分数显示正确但行内容不对。咱们换个思路,用窗口函数就能精准拿到每个采购数量下优先级最高的价格行。
问题根源
原来的查询里,GROUP BY t.product_variant_id, t.qty 后,MAX(score)只能得到每个组的最高分,但MySQL(假设你使用的是MySQL 8.0及以上版本,窗口函数需要该版本支持)没办法自动把这个分数关联到对应的原始行,所以会随机返回组内的某一行数据,这就是错误的核心原因。
解决方案:用ROW_NUMBER()窗口函数排序筛选
我们可以给每个采购数量(qty)分组内的行按你定义的优先级评分排序,然后取每个组里排名第一的行,这样就确保拿到的是优先级最高的价格数据。
完整的SQL语句如下:
SELECT id, product_variant_id, customer_group_id, price, qty, customer_id FROM ( SELECT t.*, -- 计算优先级分数并排序,客户组匹配优先级高于客户匹配 ROW_NUMBER() OVER ( PARTITION BY t.qty ORDER BY IF(t.customer_group_id = 1, 100, 0) + IF(t.customer_id = 1, 10, 0) DESC ) AS row_rank FROM tierprice t WHERE t.product_variant_id = 110 AND (t.customer_id = 1 OR t.customer_id IS NULL) AND (t.customer_group_id = 1 OR t.customer_group_id IS NULL) ) ranked_tiers WHERE row_rank = 1;
逻辑解释
- PARTITION BY t.qty:把数据按采购数量分组,每个数量组单独处理
- ORDER BY 评分 DESC:按照你定义的规则计算分数(客户组匹配得100分,客户匹配得10分),倒序排列后,分数最高的行排在组内第一位
- ROW_NUMBER():给每个组内的行按排序结果编号,
row_rank = 1就是每个数量组里优先级最高的行
执行这个查询后,会返回你期望的ID为2和3的行:
- qty=2时,客户组1的价格7000(优先级高于客户1的8000)
- qty=5时,客户组1的价格6000(优先级高于客户1的5000)
补充说明
如果你需要支持多个行分数相同的场景(比如同一qty下有两个客户组匹配的行,不过你的表唯一键约束no_duplicate_prices应该避免了这种情况),可以把ROW_NUMBER()换成RANK(),这样分数相同的行会拿到相同的排名,你可以根据需求调整筛选条件。
内容的提问来源于stack exchange,提问作者skirato




