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
相关产品推荐
相关产品推荐

