如何合并两条SELECT SQL查询 获取去重昵称的最优获胜游戏记录
合并SQL查询实现方案
需求说明
需要将两条分步SQL合并为单条独立查询,实现效果:从Games表中获取所有获胜游戏对应的最优时长、分数记录,返回结果中玩家昵称(Pseudo)不重复。
原分步查询逻辑
原两条SQL的执行逻辑拆分如下:
- 第一步筛选基础数据:查询所有满足「时间格式非空、分数非空、游戏结果为Win」的不重复玩家昵称,按游戏日期倒序排列
SELECT DISTINCT Pseudo FROM Games WHERE Time_Format IS NOT NULL AND Score IS NOT NULL AND Result = 'Win' ORDER BY Date DESC
- 第二步取单玩家最优记录:遍历第一步得到的每个玩家昵称,在相同过滤条件的获胜记录中,按时长升序、分数倒序排序,取第一条作为该玩家的最优记录
SELECT ID_Game,Time_Format,Time,Score,Date FROM Games WHERE Time_Format IS NOT NULL AND Score IS NOT NULL AND Result = 'Win' AND Pseudo = 【第一步查询得到的单个昵称】 ORDER BY Time ASC,Score DESC LIMIT 1
单条查询实现(兼容主流数据库MySQL8+/PostgreSQL/SQL Server等)
使用窗口函数实现分组内排序取Top1,是最简洁、性能最好的实现方式:
SELECT ID_Game, Pseudo, Time_Format, Time, Score, Date FROM ( SELECT *, ROW_NUMBER() OVER ( PARTITION BY Pseudo ORDER BY Time ASC, Score DESC ) AS rank_num FROM Games WHERE Time_Format IS NOT NULL AND Score IS NOT NULL AND Result = 'Win' ) t WHERE rank_num = 1 ORDER BY Date DESC;
逻辑说明
- 内层子查询先统一做数据过滤,仅保留符合条件的获胜记录
- 通过
ROW_NUMBER()窗口函数按Pseudo字段分组,组内严格按照「时长越短优先级越高、相同时长下分数越高优先级越高」的规则给每条记录生成排名序号 - 外层查询仅保留每个分组内排名为1的记录,即每个玩家的最优获胜记录,最终按游戏日期倒序返回,和原第一步查询的排序规则保持一致
低版本数据库兼容写法(不支持窗口函数场景,如MySQL5.x)
如果使用的数据库版本不支持窗口函数,可以通过关联聚合结果的方式实现:
SELECT g1.* FROM Games g1 INNER JOIN ( SELECT Pseudo, MIN(Time) AS best_time, MAX(Score) AS best_score FROM Games WHERE Time_Format IS NOT NULL AND Score IS NOT NULL AND Result = 'Win' GROUP BY Pseudo ) g2 ON g1.Pseudo = g2.Pseudo AND g1.Time = g2.best_time AND g1.Score = g2.best_score WHERE g1.Time_Format IS NOT NULL AND g1.Score IS NOT NULL AND g1.Result = 'Win' ORDER BY g1.Date DESC;
示例数据验证结果
基于提供的测试数据,查询返回结果如下,无重复昵称,每条均为对应玩家的最优获胜记录:
| ID_Game | Pseudo | Time_Format | Time | Score | Date |
|---|---|---|---|---|---|
| 1 | bob | 00:22 | 22 | 125 | 2022-06-22 13:47:43 |
| 1 | bob3 | 00:36 | 36 | 650 | 2022-06-22 13:22:22 |
| 1 | bob4 | 00:40 | 40 | 378 | 2022-06-22 13:12:22 |
内容的提问来源于stack exchange,提问作者Jxprent
相关产品推荐
相关产品推荐

