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,不要使用字符串类型或可能产生精度误差的浮点类型。
备注:内容仅供参考。
