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

Laravel Eloquent查询中如何同时获取数据与amount字段总和

解决Laravel Eloquent查询中同时获取列表与总和的问题

你遇到的问题很典型——直接在查询中添加SUM()聚合函数会导致结果集被合并成单条记录,因为聚合函数默认会把所有匹配的行归为一个分组。下面给你几种高效的解决方案:

方案一:克隆查询单独计算总和(推荐)

这是性能最优的方式,通过克隆已构建好的查询条件来计算总和,同时保留原有的分页逻辑:

// 构建基础查询条件
$query = SalesPayment::with(['abc.xyz'])
    ->whereHas('abc.xyz', function ($query) use ($options) {
        $query->where('xyz_id', $options['xyz_id']);
    })
    ->where([
        'key3' => key3(),
        'payment_status' => PAYMENT_STATUS_SUCCESS
    ])
    ->orderBy('created_at', 'desc');

// 克隆查询并计算符合条件的所有记录的amount总和
$totalSaleAmount = $query->clone()->sum('amount');

// 执行分页查询
$paginatedResults = $query->paginate(config('constants.PAGE_LIMIT'));

// 将总和附加到分页结果中(可选,根据你的返回格式调整)
$paginatedResults->append('total_sale_amount', $totalSaleAmount);
// 或者返回包含总和与分页数据的数组
return [
    'data' => $paginatedResults->items(),
    'total_sale_amount' => $totalSaleAmount,
    'pagination' => [
        'current_page' => $paginatedResults->currentPage(),
        'last_page' => $paginatedResults->lastPage(),
        'per_page' => $paginatedResults->perPage(),
        'total_records' => $paginatedResults->total()
    ]
];

为什么这个方案好用?

  • 复用了已有的查询条件,避免重复写where/whereHas逻辑
  • 只执行两次查询:一次分页、一次总和,性能开销极低
  • 完美保留原有的分页功能,不会破坏原有业务逻辑

方案二:使用子查询在每条记录中携带总和(不推荐用于大数据量)

如果你希望总和直接出现在每条返回的记录中,可以用子查询实现,但要注意这种方式在数据量大时会有性能损耗(每条记录都会执行一次子查询):

$query = SalesPayment::with(['abc.xyz'])
    ->whereHas('abc.xyz', function ($query) use ($options) {
        $query->where('xyz_id', $options['xyz_id']);
    })
    ->where([
        'key3' => key3(),
        'payment_status' => PAYMENT_STATUS_SUCCESS
    ])
    ->selectRaw('
        *,
        (SELECT SUM(amount) 
         FROM sales_payments sp
         WHERE sp.key3 = ? 
           AND sp.payment_status = ?
           AND EXISTS (
               SELECT 1 FROM abc a 
               WHERE a.id = sp.abc_id 
               AND EXISTS (
                   SELECT 1 FROM xyz x 
                   WHERE x.id = a.xyz_id 
                   AND x.id = ?
               )
           )) AS total_sale_amount
    ', [key3(), PAYMENT_STATUS_SUCCESS, $options['xyz_id']])
    ->orderBy('created_at', 'desc')
    ->paginate(config('constants.PAGE_LIMIT'));

return $query;

为什么你的原方案会失败?

当你在select中添加SUM(amount)时,MySQL会将所有匹配的行视为一个分组(因为没有指定GROUP BY),所以最终只会返回一条包含总和的记录,自然丢失了原本的多条分页数据。

内容的提问来源于stack exchange,提问作者Radhe Shyam Sharma

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 09:06:44