按指定字段分组后选取含另一字段最小值的全量行数据(以id字段打破平局)
解决分组取最小points且平局选最小id的问题
你的问题很典型:原查询只筛选出了每个game分组里points最小的记录,但没处理同分组内多个记录共享最小points的平局场景,导致返回重复行。我们可以用窗口函数ROW_NUMBER()来优雅解决这个问题,同时满足"平局时选id更小的行"的要求。
优化后的SQL方案
-- 若要返回全量字段,直接替换为g.*即可 SELECT g.id, g.game, g.points, g.hash FROM ( SELECT *, -- 按game分组,先按points升序取最小值,再按id升序处理平局 ROW_NUMBER() OVER ( PARTITION BY game ORDER BY points ASC, id ASC ) AS row_num FROM games ) g WHERE g.row_num = 1;
代码逻辑解释
PARTITION BY game:将数据按game字段划分成独立的分组ORDER BY points ASC, id ASC:每个分组内先按points从小到大排序(确保最小的points排在最前);如果出现points相同的平局情况,再按id从小到大排序,保证id更小的记录优先级更高ROW_NUMBER():为每个分组内的行分配唯一序号,符合排序规则的目标行序号会被标记为1- 外层查询仅保留
row_num = 1的记录,即可得到每个分组内唯一符合要求的行
方案优势对比
和你原来的自连接方案相比:
- 逻辑更直观,不需要额外的聚合子查询再做表关联
- 原生处理平局场景,不会返回重复行
- 支持直接返回全量字段(把外层SELECT的字段替换为
g.*),完美适配你实际表包含更多字段的需求
用你的示例数据测试,这个查询会精准返回期望结果:
id game points hash
2 x 1 fd8
2 y 2 df8
3 z 2 z89w
内容的提问来源于stack exchange,提问作者Danny B
相关产品推荐
相关产品推荐

