MySQL技术求助:统计玩家赛事获胜次数,每对手仅计首次结果
嘿,我来帮你解决这个玩家获胜次数统计的问题!你的需求核心是每对玩家只取最早对战的结果来统计获胜次数,用窗口函数来处理这个场景会比单纯的ORDER BY更高效且逻辑清晰,下面是具体的解决方案:
解决方案步骤
1. 先筛选每对玩家的最早对战记录
首先我们需要确保每两名玩家之间只保留gametime最早的那场对战。这里用LEAST()和GREATEST()函数把玩家对统一成无序的组合(比如player1=A, player2=B和player1=B, player2=A会被视为同一组),再通过ROW_NUMBER()窗口函数为每组记录按时间排序,标记出最早的那条记录:
WITH earliest_battles AS ( SELECT player1, player2, result, -- 按玩家对分组,按对战时间升序排序,标记最早的记录为rn=1 ROW_NUMBER() OVER ( PARTITION BY LEAST(player1, player2), GREATEST(player1, player2) ORDER BY gametime ASC ) AS rn FROM battles )
2. 基于最早对战记录统计获胜次数
接下来从筛选后的最早对战记录里,把获胜的玩家提取出来并统计次数。根据你的描述,result=1代表player1获胜;如果存在player2获胜的场景(比如result=2,你可以根据实际业务调整这个值),也需要纳入统计:
WITH earliest_battles AS ( SELECT player1, player2, result, ROW_NUMBER() OVER ( PARTITION BY LEAST(player1, player2), GREATEST(player1, player2) ORDER BY gametime ASC ) AS rn FROM battles ) SELECT player_id, COUNT(*) AS win_count FROM ( -- 收集player1获胜的记录 SELECT player1 AS player_id FROM earliest_battles WHERE rn = 1 AND result = 1 UNION ALL -- 收集player2获胜的记录(如果有对应result值的话,这里假设是result=2) SELECT player2 AS player_id FROM earliest_battles WHERE rn = 1 AND result = 2 ) AS all_wins GROUP BY player_id ORDER BY win_count DESC;
为什么这个方案更优?
相比你之前尝试的ORDER BY battles.player2,这个方案的优势在于:
- 逻辑更清晰:通过窗口函数的分区功能,直接明确地为每对玩家分组并筛选最早记录,不需要额外的去重操作
- 性能更高效:窗口函数的分区排序在大数据量下比多次
ORDER BY后去重的性能更好,数据库可以更高效地处理分组逻辑 - 扩展性强:如果后续需要调整对战结果的判定规则(比如增加平局处理、不同result值的定义),只需要修改子查询里的条件即可
如果你的业务里不存在player2获胜的场景,只需要去掉UNION ALL后面的部分即可。
内容的提问来源于stack exchange,提问作者Clain29
相关产品推荐
相关产品推荐

