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

如何将含SELECT子查询的指定SQL转换为Yii2 ActiveRecord查询?

当然可以!根据你提供的模型关联和原SQL语句,我们可以轻松把它转换成Yii2 ActiveRecord查询,下面提供几种不同的实现方案,你可以根据自己的场景选择:

方案一:直接对齐原SQL的子查询写法(性能最优,推荐)

这个方案完全复刻你原SQL的逻辑,通过addSelect添加两个计数子查询,全程只执行一次SQL语句,性能和原SQL一致:

use yii\db\Expression;
use yii\db\Query;

// 构建查询
$prodiQuery = ProdiPenerima::find()
    ->select('*') // 选中prodi_penerima表的所有字段
    ->alias('a') // 和原SQL保持一致的表别名
    ->addSelect([
        'jum1' => (new Query())
            ->select('count(*)')
            ->from('pendaftar')
            ->where(['prodi_pilihan_1' => new Expression('a.id_prodi_penerima')]),
        'jum2' => (new Query())
            ->select('count(*)')
            ->from('pendaftar')
            ->where(['prodi_pilihan_2' => new Expression('a.id_prodi_penerima')])
    ]);

// 获取结果集
$prodiList = $prodiQuery->all();

// 访问数据示例
foreach ($prodiList as $prodi) {
    echo "专业ID:{$prodi->id_prodi_penerima} | 第一志愿人数:{$prodi->jum1} | 第二志愿人数:{$prodi->jum2}\n";
}
方案二:利用现有关联关系简化代码

你的ProdiPenerima模型已经定义了pendaftars(对应第一志愿关联)和pendaftars0(对应第二志愿关联),我们可以基于这些关联来构建计数子查询,代码更贴合Yii2的ActiveRecord风格:

use yii\db\Expression;

$prodiQuery = ProdiPenerima::find()
    ->select('*')
    ->addSelect([
        'jum1' => Pendaftar::find()
            ->select('count(*)')
            ->where(['prodi_pilihan_1' => new Expression(ProdiPenerima::tableName() . '.id_prodi_penerima')]),
        'jum2' => Pendaftar::find()
            ->select('count(*)')
            ->where(['prodi_pilihan_2' => new Expression(ProdiPenerima::tableName() . '.id_prodi_penerima')])
    ]);

// 获取结果和访问方式和方案一完全一致
$prodiList = $prodiQuery->all();
方案三:模型内添加Getter方法(小数据量场景适用)

如果你的数据量不大,可以在ProdiPenerima模型中添加两个Getter方法,直接通过已有的关联关系获取计数,代码最简洁,但会产生N+1查询问题(每个Prodi模型会单独执行一次count查询),数据量大时性能会受影响:

// 在ProdiPenerima模型类中添加以下方法
public function getJum1()
{
    // 直接利用已定义的pendaftars关联统计数量
    return $this->getPendaftars()->count();
}

public function getJum2()
{
    // 利用pendaftars0关联统计第二志愿数量
    return $this->getPendaftars0()->count();
}

使用时直接访问模型属性即可:

$prodiList = ProdiPenerima::find()->all();
foreach ($prodiList as $prodi) {
    echo "专业ID:{$prodi->id_prodi_penerima} | 第一志愿人数:{$prodi->jum1} | 第二志愿人数:{$prodi->jum2}\n";
}
额外提示
  • 如果需要对jum1或jum2进行排序,直接在查询中添加orderBy即可,比如$prodiQuery->orderBy('jum1 DESC');
  • 方案一和方案二都支持分页,直接调用->offset($offset)->limit($limit)就能实现分页查询;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:53:41