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

如何在Yii2模型中以Join形式编写指定MySQL关联查询

嘿,我来帮你搞定Yii2里的MySQL Join查询问题!下面分两部分说明:先讲通用的Join实现方法,再把你给出的原生SQL转换成Yii2模型中的标准写法。

在Yii2中编写Join查询的通用方法

Yii2的ActiveQuery提供了两种主流的Join实现方式,根据场景选择即可:

1. 手动指定Join条件(适合复杂自定义场景)

用innerJoin()、leftJoin()这类方法直接写关联逻辑,和原生SQL思路完全一致:

// 示例:从User模型关联Order表
$query = User::find()
    ->select(['user.id', 'user.name', 'order.order_no'])
    ->innerJoin('order', 'order.user_id = user.id');

2. 利用模型关联(推荐,符合ActiveRecord规范)

如果你的模型已经定义了hasOne/hasMany这类关联关系,用joinWith()可以自动处理Join条件,代码更简洁易维护:

// 假设User模型已定义getOrders()关联方法
$query = User::find()
    ->joinWith('orders') // 自动关联order表并应用预设条件
    ->select(['user.*', 'order.order_no']);

针对你给出的SQL语句的转换方案

首先先明确模型与数据库表的对应关系(假设你已经创建了以下模型):

  • Student → students 表
  • StudentRegistration → student_registration 表
  • StudentPaperResult → student_paper_results 表
  • Paper → papers 表

方式一:手动构建Inner Join(和原生SQL逻辑完全匹配)

直接把各个表的关联条件写进innerJoin(),和你原来的SQL逻辑一致:

use app\models\StudentPaperResult;

$query = StudentPaperResult::find()
    ->select([
        'spr.id',
        'spr.total_marks',
        'spr.obtained_marks',
        'p.paper_title',
        'p.exam_id',
        'p.subject_id',
        'sr.reg_no',
        'sr.student_id',
        's.student_name'
    ])
    ->alias('spr') // 给主表起别名,和原生SQL一致
    ->innerJoin('students s', 's.id = spr.student_id')
    ->innerJoin('student_registration sr', 's.id = sr.student_id')
    ->innerJoin('papers p', 'p.id = spr.paper_id');

// 执行查询获取结果
$results = $query->all();

方式二:利用模型关联的joinWith(更推荐)

先给各个模型定义好关联关系:

  1. 在StudentPaperResult模型中添加:
// 关联Student模型
public function getStudent()
{
    return $this->hasOne(Student::class, ['id' => 'student_id']);
}

// 关联Paper模型
public function getPaper()
{
    return $this->hasOne(Paper::class, ['id' => 'paper_id']);
}
  1. 在Student模型中添加:
// 关联StudentRegistration模型
public function getStudentRegistration()
{
    return $this->hasOne(StudentRegistration::class, ['student_id' => 'id']);
}

然后就可以用joinWith()优雅地构建查询:

use app\models\StudentPaperResult;

$query = StudentPaperResult::find()
    ->select([
        'student_paper_results.id',
        'student_paper_results.total_marks',
        'student_paper_results.obtained_marks',
        'papers.paper_title',
        'papers.exam_id',
        'papers.subject_id',
        'student_registration.reg_no',
        'student_registration.student_id',
        'students.student_name'
    ])
    // 链式关联:StudentPaperResult关联Student,Student再关联StudentRegistration,同时关联Paper
    ->joinWith(['student', 'student.studentRegistration', 'paper']);

// 获取结果集
$results = $query->all();

额外提示

  • 两种方式最终生成的SQL和你给出的原生SQL完全一致;
  • 如果需要添加筛选条件,直接在查询链后追加where()即可,比如:
    $query->where(['papers.exam_id' => 101]); // 筛选exam_id为101的结果
    
  • 方式二更适合长期维护,后续修改关联逻辑只需要调整模型中的关联方法即可。

内容的提问来源于stack exchange,提问作者Sajid Mehmood

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:21:08