You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:37:21