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

Laravel Eloquent如何查询关联Assignment满足指定type条件的Survey记录

问题原因

你原有查询的逻辑和需求完全相反:你使用了whereNotExists加orWhereNotExists的组合,最终筛选出来的是「缺少1/2/3/4中任意一种Assignment的Survey」,同时还漏掉了对type=0的校验,所以达不到预期效果。

正确实现

你已经定义了assignments的hasManyThrough关联,直接基于这个关联写查询即可,不需要手动编写原生联表SQL,有两种常用实现方式:

方式1:直观写法(逻辑清晰,兼容性好)

$schedulables = Survey::whereNotNull('installer_id')
    // 依次校验5种type的Assignment都存在
    ->whereHas('assignments', fn($q) => $q->where('type', 0))
    ->whereHas('assignments', fn($q) => $q->where('type', 1))
    ->whereHas('assignments', fn($q) => $q->where('type', 2))
    ->whereHas('assignments', fn($q) => $q->where('type', 3))
    ->whereHas('assignments', fn($q) => $q->where('type', 4))
    // 预加载关联,需要返回对应Assignment的话可以加上assignments
    ->with(['customer', 'installer', 'installation', 'assignments'])
    ->latest('updated_at')
    ->get();

方式2:统计优化写法(代码更简洁)

$schedulables = Survey::whereNotNull('installer_id')
    ->whereHas('assignments', function ($query) {
        $query->whereIn('type', [0,1,2,3,4])
              ->groupBy('installation_id')
              ->havingRaw('COUNT(DISTINCT type) = 5');
    })
    ->with(['customer', 'installer', 'installation', 'assignments'])
    ->latest('updated_at')
    ->get();

说明

两种写法效果完全一致:

  • 方式1的逻辑更直观,每个whereHas单独校验一种type的关联记录存在,5个条件同时满足才会被筛选出来
  • 方式2通过统计关联Assignment中符合要求的type去重数量等于5,实现同样的筛选效果,代码更简洁

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 04:57:03