You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Laravel实现学生总分排名(支持同分同名次)

Laravel 学生同分并列排名实现方案

需求规则:按学生总分从高到低排序,总分越高排名越靠前,总分相同的学生排名一致。

前置准备:模型关联

首先在Student模型中定义和成绩表的一对多关联,方便后续业务复用:

// app/Models/Student.php
public function marks()
{
    return $this->hasMany(Mark::class, 'id_student');
}

对应Mark模型中定义反向关联即可:

// app/Models/Mark.php
public function student()
{
    return $this->belongsTo(Student::class, 'id_student');
}

场景1:获取全量带排名的学生列表

核心逻辑:先聚合每个学生的总分并按分数降序排序,遍历集合时动态计算排名——分数和上一位相同则沿用相同排名,分数低于上一位则更新排名为当前遍历位置+1(索引从0开始)。

// 聚合所有学生总分,无成绩的学生总分记为0
$students = Student::select('students.id', 'students.name', 'students.class_id')
    ->selectRaw('COALESCE(SUM(marks.mark), 0) as total_score')
    ->leftJoin('marks', 'students.id', '=', 'marks.id_student')
    ->groupBy('students.id', 'students.name', 'students.class_id')
    ->orderByDesc('total_score')
    ->get();

// 处理并列排名
$currentRank = 1;
$lastScore = null;
$rankedList = $students->map(function ($student, $index) use (&$currentRank, &$lastScore) {
    if (!is_null($lastScore) && $student->total_score < $lastScore) {
        $currentRank = $index + 1;
    }
    $student->rank = $currentRank;
    $lastScore = $student->total_score;
    return $student;
});

返回结果示例(对应给出的测试数据):

idnametotal_scorerank
4Mark1201
2Frank1152
3Bright903
1Emma04

如果后续出现两个学生同分,比如两个120分,两人rank都是1,下一位115分的学生rank直接为3,符合并列排名规则。

场景2:查询单个学生的排名

如果只需要查指定学生的排名,不需要拉取全量列表遍历,可以直接通过子查询计算,性能更高:

$targetStudentId = 2; // 传入要查询的学生ID
// 先拿到学生总分
$student = Student::select('id', 'name')
    ->selectRaw('COALESCE(SUM(marks.mark), 0) as total_score')
    ->leftJoin('marks', 'id', '=', 'marks.id_student')
    ->groupBy('id', 'name')
    ->find($targetStudentId);

if ($student) {
    // 排名 = 总分比当前学生高的人数 + 1
    $student->rank = Student::leftJoin('marks', 'students.id', '=', 'marks.id_student')
        ->groupBy('students.id')
        ->havingRaw('SUM(marks.mark) > ?', [$student->total_score])
        ->count() + 1;
}

优化提示

  • 如果需要按班级维度排名,只需要在上述所有查询中增加where('class_id', $classId)条件即可,排名逻辑无需调整
  • 当学生数据量超过10万级时,建议给marks表的id_student字段添加索引,大幅提升聚合查询速度
  • 排名计算逻辑如果需要多处复用,可以封装成自定义集合方法或者公共Helper函数,避免重复写代码

内容的提问来源于stack exchange,提问作者Bezara Florent

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 13:27:33