EF Core中获取IQueryable分数理论排名(无需实例化列表)
实现任意游戏尝试记录的排名计算(基于EF Core IQueryable)
核心思路
要满足你的需求,核心逻辑是:目标记录的排名 = 数据库中严格大于目标分数的不同分数的数量 + 1。这个逻辑同时适用于记录存在或不存在的情况,且天然支持同分取最高排名的规则——所有同分记录对应的高分数数量完全一致,因此排名相同。
代码实现
以下是基于EF Core IQueryable的实现,全程不会将集合转换为IEnumerable,所有操作都会被翻译为PostgreSQL SQL在数据库端执行:
public static int GetAttemptRank(IQueryable<Attempt> attempts, Attempt targetAttempt) { // 统计所有严格大于目标分数的不同分数的数量 int higherUniqueScoresCount = attempts .Where(attempt => attempt.score > targetAttempt.score) .Select(attempt => attempt.score) .Distinct() .Count(); // 排名 = 高分数数量 + 1 return higherUniqueScoresCount + 1; }
示例验证
针对你给出的测试场景:
- 已存在的记录(attempt1,score=30):
数据库中严格大于30的分数只有500,higherUniqueScoresCount=1,返回排名1+1=2,符合预期。 - 不存在的记录(attempt3,score=47):
严格大于47的分数只有500,higherUniqueScoresCount=1,返回排名2——该分数会排在500之后、30之前,符合“比其分数高的最低分记录之后的排名”要求。 - 同分的不存在记录(attempt2,score=30):
与已存在的30分记录计算逻辑完全一致,返回排名2,符合同分同排名的要求。
边缘情况测试
- 目标分数为全场最高(如score=600):
higherUniqueScoresCount=0,返回排名1。 - 目标分数为全场最低(如score=5):严格大于5的分数有500、30、25、20、10,共5个,返回排名
5+1=6。 - 所有记录分数相同:
higherUniqueScoresCount=0,所有记录(包括目标记录)排名均为1。
内容的提问来源于stack exchange,提问作者Tomer Trashman
相关产品推荐
相关产品推荐

