我在数据透视表中有一个值“标记”,如何使用查询生成器基于“标记”值查找学生等级?

时间:2018-11-20 16:23:44

标签: sql laravel laravel-5 php-7 laravel-query-builder

我有两个模型Exam和Student,每个学生尝试一次将由他/他获得的标记存储在数据透视表test_user中的考试之后。我需要根据获得的分数对学生进行排名。

现在,我正在为此使用效率非常低下的解决方案,其中涉及到for循环。下面是实现

            $rank=0;
            $attempts = DB::table('exam_user')
                    ->where('exam_id',$exam->id)
                    ->orderBy('marks','desc')
                    ->get();
            foreach ($attempts as $attempt) {
                $rank++;
                if($attempt->user_id==Auth::id())
                    break;
            }

有什么方法可以不使用for循环来确定排名,只需使用laravel中的查询生成器。我想我在这里缺少一些SQL基础知识。

1 个答案:

答案 0 :(得分:0)

排名是拥有比您的价值+ 1更大的价值的人数。

因此,您可以执行以下操作:

$userMarks = DB::table('exam_user')
    ->select('marks')
    ->where('exam_id', $exam->id)
    ->where('user_id', '=', Auth::id())
    ->firstOrFail()
    ->marks;

$rank = DB::table('exam_user')
    ->where('exam_id', $exam->id)
    ->where('marks', '>', $userMarks)
    ->count() + 1;

您还可以将其放入一个查询中:

$userId = Auth::id();
$rank = DB::table('exam_user')
            ->where('exam_id', $exam->id)
            ->whereRaw(
                "marks > (select eu2.marks from exam_user eu2 where eu2.exam_id = {$exam->id} and eu2.user_id = {$userId}) limit 1"
            )
            ->count() + 1;

您还可以考虑将数据透视表exam_user用作实际模型,并将其命名为Marks,因为它包含您要查询的重要数据。

然后可以将以下内容添加到Exam模型中:

Class Exam {
    // ...
    public function marks() {
        $this->hasMany(Marks::class);
    }    
    // ...
}

这意味着您可以执行以下操作:

$userId = Auth::id();
$rank = $exam->marks()
            ->whereRaw(
                "marks > (select marks from exam_user where exam_id = {$exam->id} and user_id = {$userId}) limit 1"
            )
            ->count() + 1;