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

Laravel中如何基于关联模型的最新实例筛选主模型?

Laravel中如何基于关联模型的最新实例筛选主模型?

嘿,这个需求我之前做项目时刚好碰到过!要基于关联模型的最新记录筛选主模型,而且得用查询构造器保证大数据量下的性能,确实得找对方法。下面给你几种实用的方案,你可以根据自己的Laravel版本和业务场景选:

1. 最简洁的方案:利用Laravel的latestOfMany()关联(Laravel 8+适用)

首先在你的Product模型里定义一个关联,专门指向最新的状态记录:

// app/Models/Product.php
public function latestStatus()
{
    // latestOfMany()会自动获取该产品的最新ProductStatus实例
    return $this->hasOne(ProductStatus::class)->latestOfMany();
}

之后直接用whereHas基于这个关联筛选就行,代码非常清爽:

$approvedProducts = Product::whereHas('latestStatus', function ($query) {
    $query->where('status', 'Approved');
})->get();

这个方法底层是Laravel帮你生成高效的子查询,既简洁又能保证性能,强烈推荐用这个!

2. 子查询+关联筛选(兼容低版本Laravel)

如果你用的是Laravel 8以下的版本,或者不想额外定义关联,可以直接用子查询来实现:

$approvedProducts = Product::whereHas('statuses', function ($query) {
    // 先获取当前产品的最新状态的创建时间(如果用自增id判断新旧,换成MAX(id)就行)
    $latestStatusTime = ProductStatus::select(DB::raw('MAX(created_at)'))
        ->whereColumn('product_id', 'products.id');
    
    $query->where('status', 'Approved')
          // 确保这条状态是该产品的最新记录
          ->where('created_at', $latestStatusTime);
})->get();

这里的核心是用子查询拿到每个产品的最新状态时间,然后在whereHas里同时匹配状态值和“是否为最新记录”两个条件。

3. JOIN结合子查询(极致性能优化)

如果你的数据量特别大,JOIN的方式可能比子查询更高效(取决于数据库引擎和索引),可以这么写:

// 先获取每个产品对应的最新状态ID
$latestStatusIds = ProductStatus::select('product_id', DB::raw('MAX(id) as latest_status_id'))
    ->groupBy('product_id');

$approvedProducts = Product::joinSub($latestStatusIds, 'latest_statuses', function ($join) {
    $join->on('products.id', '=', 'latest_statuses.product_id');
})
->join('product_statuses', 'product_statuses.id', '=', 'latest_statuses.latest_status_id')
->where('product_statuses.status', 'Approved')
->select('products.*') // 只选择产品表的字段,避免字段冲突
->get();

这种方式通过两次JOIN直接关联到最新的状态记录,筛选逻辑更直观,适合超大数据量的场景。

额外提示

不管用哪种方法,都建议给product_statuses表的product_id、status、created_at(或id)字段加上组合索引,能大幅提升查询速度!

备注:内容来源于stack exchange,提问作者Melly

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.21 11:10:28