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

Laravel模型查询中如何关联WITH子查询并优化性能?

在Laravel中关联CTE优化关联查询性能

实现思路

借助Laravel的withExpression方法定义CTE,将其关联到主查询或关联关系中,替代性能低下的子查询方案。

具体实现步骤

  • 关联CTE到offers关联关系
    先通过withExpression注册你的CTE,再在offers关联的闭包内通过join关联CTE,获取对应lead和offer的最近发送时间:

    $leads = Lead::withExpression('last_sent_at', function ($query) {
        $query->select('offer_id', 'lead_id', DB::raw('max(created_at) as sent_at'))
              ->from('offer_history')
              ->groupBy('offer_id', 'lead_id');
    })
    ->with([
        // 保留原有其他关联
        'offers' => function ($query) {
            $query->join('last_sent_at', function ($join) {
                $join->on('offers.id', '=', 'last_sent_at.offer_id')
                     ->on('last_sent_at.lead_id', '=', DB::raw('leads.id'));
            })
            ->select('offers.*', 'last_sent_at.sent_at');
        }
    ])
    ->filters()
    ->get();
    
  • 将最近发送时间挂载到Lead模型
    若希望把最近发送时间直接作为Lead的属性,可通过left join关联CTE:

    $leads = Lead::withExpression('last_sent_at', function ($query) {
        $query->select('lead_id', DB::raw('max(created_at) as latest_sent_at'))
              ->from('offer_history')
              ->groupBy('lead_id');
    })
    ->leftJoin('last_sent_at', 'leads.id', '=', 'last_sent_at.lead_id')
    ->with([/* 原有关联 */])
    ->filters()
    ->select('leads.*', 'last_sent_at.latest_sent_at')
    ->get();
    

关键说明

  • withExpression是Laravel 8及以上版本支持的方法,能高效定义CTE,在大数据量场景下性能优于子查询。
  • 关联时需确保lead_id和offer_id的关联条件准确,避免数据匹配错误。
  • 若offers是通过offer_history建立的多对多关联,可调整关联逻辑,直接在中间表关联中引入CTE。

内容的提问来源于stack exchange,提问作者Константин Джанов

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 09:12:41