Laravel查询求助:如何获取所有考试的平均分数
解决Laravel中获取所有考试平均分的问题
我完全懂你的困扰——左连接的思路是对的,但大概率是没处理好聚合函数的空值情况,或者分组逻辑没写对。咱们直接上可行的解决方案,分两种方式:查询构建器和Eloquent关联,你可以选适合自己的。
方法一:使用查询构建器(Query Builder)
直接用DB门面来写左连接,配合COALESCE函数把空值转成0(如果想要NULL的话去掉COALESCE就行),同时记得按考试的id和名称分组:
$examAverages = DB::table('exams') ->leftJoin('student_scores', 'exams.id', '=', 'student_scores.exam_id') ->select( 'exams.exam_name', DB::raw('COALESCE(AVG(student_scores.score), 0) AS average_score') ) ->groupBy('exams.id', 'exams.exam_name') ->get();
关键说明:
LEFT JOIN确保即使没有对应分数记录的考试(比如Third Exam)也会被保留在结果里AVG(student_scores.score)计算平均分,但没有分数时会返回NULLCOALESCE(..., 0)把NULL替换成0,如果你想要保留NULL,直接用AVG(student_scores.score) AS average_score即可- 分组时要包含
exams.id和exams.exam_name,避免因数据库模式(比如MySQL的ONLY_FULL_GROUP_BY)导致的报错
方法二:使用Eloquent关联(更优雅)
如果你的项目用了Eloquent模型,先给Exam模型定义和分数表的关联:
// app/Models/Exam.php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; class Exam extends Model { protected $table = 'exams'; public function scores(): HasMany { return $this->hasMany(StudentScore::class, 'exam_id'); } }
然后用Eloquent的withAvg方法来直接获取平均分,再处理空值:
use App\Models\Exam; $examAverages = Exam::query() ->select('id', 'exam_name') ->withAvg('scores as average_score', 'score') ->get() ->map(function ($exam) { // 把NULL转成0,不需要的话删掉这行 $exam->average_score = $exam->average_score ?? 0; return $exam; });
效果验证
执行以上任意一种方法后,你都会得到符合期望的结果:
| exam_name | average_score |
|---|---|
| First Exam | 12.33 |
| Second Exam | 12 |
| Third Exam | 0 |
如果想要Third Exam显示NULL,只需要去掉COALESCE或者map里的空值替换逻辑就行。
内容的提问来源于stack exchange,提问作者Francis Rubia
相关产品推荐
相关产品推荐

