Laravel中用DB::raw在Select中调用Where子句,统计多类型问题数量
解决方案:按问题类型统计数量
你的核心问题是没有针对问题类型做分组条件统计,所以只能拿到总数量。下面给你两种适配不同场景的实现方式:
方式1:用Eloquent关联预加载(推荐,符合Laravel最佳实践)
首先确保你的模型关联已经正确定义:
// TestTemplate模型 class TestTemplate extends Model { public function sections() { return $this->hasMany(Section::class); } // 通过sections关联到questions的间接关联 public function questions() { return $this->hasManyThrough(Question::class, Section::class); } }
然后查询时用withCount方法,一次性预加载总数量和各类型的统计数,避免N+1查询问题:
// 获取所有测试模板及对应的问题统计 $testTemplates = TestTemplate::withCount([ 'questions', // 总问题数,会生成`questions_count`属性 'questions as mcq_count' => function ($query) { $query->where('type', 'MCQ'); // 统计MCQ类型的数量 }, 'questions as coding_submission_count' => function ($query) { $query->where('type', 'Coding Submission'); // 统计编程提交类型的数量 } ])->get();
之后遍历输出时,直接访问这些预加载的统计属性即可:
foreach ($testTemplates as $template) { echo "模板名称: {$template->name}<br>"; echo "总问题数: {$template->questions_count}<br>"; echo "MCQ数量: {$template->mcq_count}<br>"; echo "编程提交数量: {$template->coding_submission_count}<br><br>"; }
方式2:用DB查询构建器直接关联查询
如果不想用Eloquent关联,也可以直接写原生风格的关联查询,通过CASE语句分组统计:
$testTemplateStats = DB::table('test_templates') ->leftJoin('sections', 'test_templates.id', '=', 'sections.test_template_id') ->leftJoin('questions', 'sections.id', '=', 'questions.section_id') ->select( 'test_templates.id', 'test_templates.name', DB::raw('COUNT(questions.id) as total_questions'), // 总数量 DB::raw('SUM(CASE WHEN questions.type = "MCQ" THEN 1 ELSE 0 END) as mcq_count'), // MCQ数量 DB::raw('SUM(CASE WHEN questions.type = "Coding Submission" THEN 1 ELSE 0 END) as coding_count') // 编程提交数量 ) ->groupBy('test_templates.id', 'test_templates.name') // 按测试模板分组 ->get();
遍历输出的方式和上面一致,直接访问对应的字段即可。
为什么你的原有代码不行?
你之前的leftJoin只是把三张表关联起来,但没有按测试模板分组,也没有针对问题类型做条件统计,所以最终只能拿到所有问题的总数,无法拆分出各类型的数量。上面两种方式都解决了这两个核心问题。
内容的提问来源于stack exchange,提问作者Asif Nawaz
相关产品推荐
相关产品推荐

