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

Laravel中如何在whereHas中使用一对多关系的特定元素

解决方案:基于关联表最后一条特定记录筛选主表数据

方法一:使用whereExists结合子查询定位最后一条记录

这种方法通过子查询精准锁定每个主表记录对应的最后一条特定类型关联记录,再判断其是否满足日期条件:

$shipments = Shipment::whereExists(function ($query) use ($startDate) {
    $query->select(DB::raw(1))
          ->from('shipment_stops')
          ->whereColumn('shipment_stops.shipment_id', 'shipments.id')
          ->where('shipment_stops.type', 'your_target_type') // 替换为你的特定类型标识
          ->where('shipment_stops.departure_date', '>=', $startDate)
          // 确保是当前shipment的最后一条特定类型停靠点
          ->whereRaw('shipment_stops.id = (SELECT MAX(id) FROM shipment_stops WHERE shipment_id = shipments.id AND type = "your_target_type")');
});

方法二:通过子查询聚合最后记录后关联筛选

先聚合出每个主表记录对应的最后一条特定类型关联记录,再通过关联筛选满足条件的主表数据:

// 子查询:获取每个shipment的最后一条特定类型停靠点ID
$lastTargetStops = DB::table('shipment_stops')
    ->select('shipment_id', DB::raw('MAX(id) as last_stop_id'))
    ->where('type', 'your_target_type') // 替换为你的特定类型标识
    ->groupBy('shipment_id');

// 关联主表和目标停靠点,筛选日期条件
$shipments = Shipment::joinSub($lastTargetStops, 'last_stops', function ($join) {
    $join->on('shipments.id', '=', 'last_stops.shipment_id');
})
->join('shipment_stops', 'last_stops.last_stop_id', '=', 'shipment_stops.id')
->where('shipment_stops.departure_date', '>=', $startDate)
->select('shipments.*') // 仅选择主表字段
->distinct(); // 避免重复数据(根据实际情况可选)

补充说明

  • 原whereHas逻辑是检查任意一条关联记录是否符合条件,而上述方法会精准定位到每个主表记录对应的最后一条特定类型关联记录,再判断其是否满足日期要求。
  • 请将代码中的your_target_type替换为实际业务中的类型值(比如'departure'或自定义的类型标识)。
  • 如果关联记录的排序依据不是id,可以将MAX(id)替换为对应的排序字段(比如MAX(created_at))来获取真正的最后一条记录。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 19:25:22