PAYATHON 2026

Laravel 中如何对两列执行算术运算并求和?

支付小周

结论

select() 会把传入的字符串当成列名,所以 sum(invoice-payment) 会被整体转义,数据库随后会查找一个并不存在的同名列。需要执行算术表达式时,应使用 selectRaw() 或 DB::raw(),并给计算结果设置别名。

public function getIndex(Request $request)
{
    $result = \DB::table('tb_accounts')
        ->selectRaw('SUM(invoice - payment) AS balance_total')
        ->first();

    $this->data['balanceTotal'] = $result->balance_total;

    return view('account.index', $this->data);
}

在 Blade 中直接输出这个标量值即可:

{{ $balanceTotal }}

错误原因

下面这段代码:

->select('sum(invoice-payment)')

查询构造器不会把参数解析成 SQL 函数,而是按普通列名处理。最终生成的 SQL 类似:

SELECT `sum(invoice-payment)` FROM `tb_accounts`

反引号说明数据库正在查找名为 sum(invoice-payment) 的列,因此会报 Unknown column 错误。

改用 selectRaw() 后,才能生成所需的算术聚合表达式:

SELECT SUM(invoice - payment) AS balance_total
FROM tb_accounts

这条语句会计算每条记录的 invoice - payment,再对所有差值求和。

使用 DB::raw() 的写法

也可以使用 DB::raw(),明确告诉查询构造器这部分是 SQL 表达式:

public function getIndex(Request $request)
{
    $result = \DB::table('tb_accounts')
        ->select(
            \DB::raw('SUM(invoice - payment) AS balance_total')
        )
        ->first();

    return view('account.index', [
        'balanceTotal' => $result->balance_total,
    ]);
}

处理 NULL 值

如果 invoice 或 payment 可能是 NULL,那么 invoice - payment 的结果也会是 NULL,SUM() 会忽略这一条结果。如果业务上需要把空值按 0 处理,可以使用 COALESCE():

$result = \DB::table('tb_accounts')
    ->selectRaw(
        'COALESCE(
            SUM(COALESCE(invoice, 0) - COALESCE(payment, 0)),
            0
        ) AS balance_total'
    )
    ->first();

$balanceTotal = $result->balance_total;

这样,即使数据表为空,或者相关字段全是 NULL,结果也会是 0。

注意事项

  • first() 返回单个结果对象,需要通过 $result->balance_total 取值。
  • 原代码中的 get() 返回集合,不适合直接输出单个合计值。
  • 不要在 selectRaw() 中直接拼接用户输入。需要添加动态条件时,应使用参数绑定或查询构造器的 where() 等方法。
  • invoice 和 payment 应使用适合金额计算的数值类型,例如 DECIMAL,不要使用字符串类型或可能产生精度误差的浮点类型。

备注:内容仅供参考。