Laravel新手求教:如何用查询构造器/Eloquent实现测验过滤SQL?
解决方案:用Eloquent和查询构造器实现测验过滤
嘿,作为Laravel新手碰到这种关联过滤的问题太正常了,我来帮你把这条SQL转换成更符合Laravel风格的Eloquent和查询构造器实现方案~
首先得先把模型关联设置好(要是还没弄的话),这样Eloquent才能正常工作:
- 在
Quiz模型(对应m_quiz表)里加关联:
public function problems() { return $this->hasMany(Problem::class, 'quiz_id'); }
- 在
Problem模型(对应m_problem表)里加关联:
public function answerChoices() { return $this->hasMany(AnswerChoice::class, 'problem_id'); }
一、Eloquent方案(首推,更贴合Laravel ORM风格)
用whereHas嵌套查询就能完美实现你的需求,还自动帮你处理很多细节:
$quizzes = Quiz::select('id', 'content') ->whereHas('problems', function ($query) { // 只保留那些关联问题有至少一个答案选项的测验 $query->whereHas('answerChoices'); }) ->distinct() // 保险起见加上去重,避免极端情况出现重复结果 ->get();
简单唠唠逻辑:
whereHas('problems'):直接筛掉那些连一个关联问题都没有的测验- 嵌套的
whereHas('answerChoices'):再把那些关联问题里连个答案选项都没有的测验也过滤掉 select('id', 'content'):和你原SQL里选的字段完全对应distinct():对应原SQL的DISTINCT,防止出现重复的测验记录
二、查询构造器方案(贴近原SQL写法)
要是你想更贴近原SQL的JOIN逻辑,用查询构造器这么写就行:
$quizzes = DB::table('m_quiz as q') ->select('q.id', 'q.content') ->distinct() ->join('m_problem as p', 'q.id', '=', 'p.quiz_id') ->join('m_answer_choice as a', 'p.id', '=', 'a.problem_id') ->get();
为啥用JOIN而不是原SQL的RIGHT JOIN?
原SQL里的RIGHT JOIN其实没必要用在这里——我们要的是有问题且问题有答案的测验,用默认的join(也就是INNER JOIN)直接就能筛选出符合条件的记录,逻辑更清晰,性能也比RIGHT JOIN好不少,毕竟不用处理那些无关联的冗余数据。
内容的提问来源于stack exchange,提问作者Nooglers BIT
相关产品推荐
相关产品推荐

