Laravel使用DB类关联三表计算评分平均值并解决重复数据
解决Laravel多表关联后教师重复显示及平均评分计算问题
嘿,我来帮你搞定这个问题!你现在遇到的两个核心问题——教师因多条评分重复显示和计算教师的平均评分,其实通过分组查询和聚合函数就能轻松解决,下面是具体的修改方案:
修改后的查询代码
$teachers = DB::table('users as u') ->leftJoin('user_infos as ui', 'u.id', '=', 'ui.user_id') ->leftJoin('ratings as r', 'u.id', '=', 'r.teacher_id') ->select([ 'u.*', 'ui.about', 'ui.first_name', 'ui.last_name', 'ui.avatar', 'ui.rate', DB::raw('AVG(r.rating) as average_rating') // 计算该教师的平均评分 ]) ->where('u.status', 1) // 按教师唯一标识及用户信息字段分组,确保每条记录对应一个教师 ->groupBy('u.id', 'ui.about', 'ui.first_name', 'ui.last_name', 'ui.avatar', 'ui.rate') ->get();
关键修改点说明
- 调整关联起点:从
users表开始关联,用leftJoin保证即使某个教师还没有评分记录,也能被纳入结果列表(如果只需要有评分的教师,换成innerJoin即可)。 - 聚合函数计算平均评分:用
DB::raw('AVG(r.rating) as average_rating')生成SQL的平均评分计算,别名average_rating方便后续在代码/视图中调用。 - 分组去重:通过
groupBy把同一个教师的所有评分记录合并成一条,分组字段要包含所有select里的非聚合字段(比如用户信息、用户表字段),避免MySQL严格模式下报错。
视图中使用示例
拿到数据后,在Blade视图里可以这样展示每个教师的卡片:
@foreach($teachers as $teacher) <div class="teacher-card"> <img src="{{ $teacher->avatar }}" alt="{{ $teacher->first_name }} {{ $teacher->last_name }}"> <h3>{{ $teacher->first_name }} {{ $teacher->last_name }}</h3> <!-- 格式化平均评分,没有评分时显示0 --> <p>平均评分: {{ number_format($teacher->average_rating ?? 0, 1) }}</p> <p>{{ $teacher->about }}</p> </div> @endforeach
这样就能完美实现每个教师只显示一次,同时展示他们的平均评分啦!
内容的提问来源于stack exchange,提问作者Kim Carlo
相关产品推荐
相关产品推荐

