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

Laravel多关联表查询:如何用单查询获取关联指定A所有B的C表记录

解决方案

核心思路

通过子查询获取目标A关联的所有B的ID集合,再通过BC表分组筛选出关联了全部这些B的C记录——利用分组后的计数等于B集合的总数来确保C关联了所有目标B,全程单次查询完成。

假设表结构

  • A表:主键id
  • AB关联表:a_id(关联A)、b_id(关联B)
  • B表:主键id
  • BC关联表:b_id(关联B)、c_id(关联C)
  • C表:主键id

方式1:使用查询构造器

$aId = 1; // 目标A记录的ID

$cs = DB::table('c')
    ->join('bc', 'c.id', '=', 'bc.c_id')
    // 子查询获取目标A关联的所有B的ID
    ->whereIn('bc.b_id', function ($sub) use ($aId) {
        $sub->select('b_id')
            ->from('ab')
            ->where('a_id', $aId);
    })
    ->groupBy('c.id', 'c.*') // 适配MySQL严格模式,需包含所有查询的C表字段
    // 筛选出关联的B数量等于目标B总数的C
    ->havingRaw('COUNT(DISTINCT bc.b_id) = (SELECT COUNT(*) FROM ab WHERE a_id = ?)', [$aId])
    ->get();

方式2:使用Eloquent模型(推荐,更贴合Laravel风格)

先确保模型已定义多对多关联:

// A模型
class A extends Model
{
    public function bs()
    {
        return $this->belongsToMany(B::class, 'ab');
    }
}

// B模型
class B extends Model
{
    public function cs()
    {
        return $this->belongsToMany(C::class, 'bc');
    }
}

// C模型
class C extends Model
{
    public function bs()
    {
        return $this->belongsToMany(B::class, 'bc');
    }
}

然后执行查询:

$aId = 1; // 目标A记录的ID

$cs = C::whereHas('bs', function ($query) use ($aId) {
    // 子查询限定只能是目标A关联的B
    $query->whereIn('b.id', function ($sub) use ($aId) {
        $sub->select('b_id')
            ->from('ab')
            ->where('a_id', $aId);
    });
}, '=', function ($countSub) use ($aId) {
    // 子查询获取目标A关联的B的总数
    $countSub->select(DB::raw('COUNT(*)'))
        ->from('ab')
        ->where('a_id', $aId);
})->get();

关键说明

  • 用COUNT(DISTINCT bc.b_id)避免BC表存在重复关联记录时的计数错误
  • 全程通过子查询嵌套实现单次SQL执行,无需循环或多次查询
  • 若MySQL关闭了ONLY_FULL_GROUP_BY模式,查询构造器中的groupBy可简化为groupBy('c.id')

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 08:57:05