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

Laravel中如何获取每个客户的最新账单记录?

问题分析

你当前的查询逻辑存在两个核心问题:

  • 使用groupBy('weekly_billing.customer_id')时,直接选择weekly_billing.*会导致数据库返回分组内任意一条记录的字段值(而非对应max(created_at)的那条),因为非聚合字段未被包含在groupBy中(MySQL严格模式下甚至会直接报错)。
  • 仅通过max(weekly_billing.created_at)获取最新时间,但无法将该时间与对应账单的其他字段关联。
解决方案

以下是几种可行的实现方式,你可以根据自己的数据库版本和需求选择:

方法1:子查询获取最新账单时间后关联

先通过子查询得到每个客户的最新账单创建时间,再关联原表和客户表筛选出对应记录:

$data = DB::table('weekly_billing')
    ->leftJoin('customers', 'weekly_billing.customer_id', '=', 'customers.id')
    ->join(
        DB::raw('(SELECT customer_id, MAX(created_at) AS latest_created FROM weekly_billing GROUP BY customer_id) AS latest_bill'),
        function ($join) {
            $join->on('weekly_billing.customer_id', '=', 'latest_bill.customer_id')
                 ->on('weekly_billing.created_at', '=', 'latest_bill.latest_created');
        }
    )
    ->select('weekly_billing.*', 'customers.customer_name')
    ->get();

方法2:使用窗口函数(推荐,需MySQL 8.0+)

利用ROW_NUMBER()窗口函数为每个客户的账单按创建时间倒序编号,然后筛选出编号为1的记录(即最新账单):

$data = DB::table(
    DB::raw('
        SELECT 
            weekly_billing.*, 
            customers.customer_name,
            ROW_NUMBER() OVER (PARTITION BY weekly_billing.customer_id ORDER BY weekly_billing.created_at DESC) AS rn
        FROM weekly_billing
        LEFT JOIN customers ON weekly_billing.customer_id = customers.id
    ') AS temp
)
->where('rn', 1)
->select('temp.*')
->get();

方法3:Eloquent模型关联方式(若使用模型)

如果你的项目中定义了Customer和WeeklyBilling模型,可以通过关联关系简化查询:

// 在Customer模型中定义关联
public function latestWeeklyBilling()
{
    return $this->hasOne(WeeklyBilling::class)->latest();
}

// 查询时直接获取
$data = Customer::with('latestWeeklyBilling')->get();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 05:30:54