我不明白为什么这不起作用:
Device::with(['travel.move.position' => function($q) use ($start, $end) {
return $q->whereBetween('created_date', [$start, $end]);
}]);
我认为它应该为我提供travel->move->position
关系的所有设备,但只包含position.datetime
介于$start
和$end
我试过像
这样的东西Device::whereHas('travel.move.position', function($q) use ($start, $end) {
return $q->whereBetween('created_date', [$start, $end]);
});
我得到了预期的结果,但我没有得到热切的关系。
为答案增加了查询1:
select *
from `devices`
where exists (
select * from `travels`
inner join `travel_info` on `travel_info`.`id` = `travels`.`info_id`
where `devices`.`id` = `travel_info`.`device_id`
and exists (
select *
from `moves`
where `moves`.`travel_id` = `travels`.`id`
and exists (
select * from `positions`
where `moves`.`position_id` = `positions`.`id` and `created_at`
between ? and ?
)
)
查询是完美的(就像whereHas一样)但是什么时候使用with():
select `travels`.*, `travel_info`.`device_id`
from `travels`
inner join `travel_info` on `travel_info`.`id` = `travels`.`info_id`
where `travel_info`.`device_id` in (?, ?, ?)
....
select * from `moves` where `moves`.`travel_id` in (?, ..., ?)
....
select * from `positions` where `positions`.`id` in (?, ..., ?)
答案 0 :(得分:2)
好的,经过与问题作者的长时间讨论,我们发现问题不是查询本身,而是with()
语句中关系的不正确加载。
我想出了以下似乎返回预期结果的查询。它首先执行主查询以使所有设备与过滤条件匹配,然后将相同的过滤器应用于我们急切加载所需的每个关系:
$start = '2016-10-01';
$end = '2016-10-31';
$devices = Device::whereHas('travel.move.position', function($q) use ($start, $end) {
$q->whereBetween('created_at', [$start, $end]);
})->with([
'travel' => function($q1) use ($start, $end) {
$q1->whereHas('move.position', function($q2) use ($start, $end) {
$q2->whereBetween('created_at', [$start, $end]);
});
},
'travel.move' => function($q1) use ($start, $end) {
$q1->whereHas('position', function($q2) use ($start, $end) {
$q2->whereBetween('created_at', [$start, $end]);
});
},
'travel.move.position' => function($q1) use ($start, $end) {
$q1->whereBetween('created_at', [$start, $end]);
}
])->get();