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

Laravel中如何使用Eloquent关联改写按来源统计线索数的查询

Eloquent关联实现方案

前置配置:定义模型关联

使用Eloquent关联查询的前提是在模型中配置好表之间的关联关系,后续所有查询会自动读取关联配置的外键、主键映射,不需要手动编写连接条件。

在Customer模型中添加与线索表的一对多关联:

// app/Models/Customer.php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Customer extends Model
{
    // 其他已有配置...

    public function leads()
    {
        return $this->hasMany(Lead::class, 'customer_id', 'id');
    }
}

可选在Lead模型中添加反向归属关联(本次统计查询非必须,其他业务场景可复用):

// app/Models/Lead.php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Lead extends Model
{
    // 其他已有配置...

    public function customer()
    {
        return $this->belongsTo(Customer::class, 'customer_id', 'id');
    }
}

核心查询实现(全版本兼容,纯Eloquent关联逻辑)

使用Laravel自带的withCount关联聚合方法,结合分组求和实现统计,不需要手动编写任何join语句,和原有手写join查询逻辑100%等价,返回结构完全匹配需求:

// 传入实际的查询时间范围
$start_date = '';
$end_date = '';

$sourceLeadStats = Customer::withCount('leads')
    ->whereBetween('created_at', [$start_date, $end_date])
    ->groupBy('source')
    ->selectRaw('source, sum(leads_count) as source_leads_count')
    ->orderBy('source_leads_count', 'DESC')
    ->get()
    ->toArray();

方案说明

  • 关联逻辑完全依赖模型中定义的leads()方法,后续如果外键、主键调整,只需要修改模型关联定义,不需要改动业务查询代码
  • 兼容Laravel 5.3及以上所有版本,不需要引入额外扩展
  • 避免了left join一对多表时产生的笛卡尔积行数膨胀问题,在leads.customer_id加有索引的场景下,查询效率高于手写join
  • 完全符合ONLY_FULL_GROUP_BY的SQL规范,不会出现SQL语法错误
  • 返回结构和需求示例完全一致,示例返回如下:
[
    [
        "source" => "facebook",
        "source_leads_count" => 1300
    ],
    [
        "source" => "google",
        "source_leads_count" => 600
    ]
]

可选:和原join逻辑生成完全相同SQL的写法(Laravel 9+)

如果需要生成和原有手写leftJoin完全一致的SQL,可以使用Laravel 9新增的leftJoinRelation方法,自动通过关联定义生成join语句,同样不需要手动编写外键连接条件:

$sourceLeadStats = Customer::select('customers.source')
    ->selectRaw('count(leads.id) as source_leads_count')
    ->leftJoinRelation('leads')
    ->whereBetween('customers.created_at', [$start_date, $end_date])
    ->groupBy('customers.source')
    ->orderBy('source_leads_count', 'DESC')
    ->get()
    ->toArray();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 23:21:41