Laravel中MySQL带条件SUM与减法运算结果异常问题
问题
需要在MySQL查询中根据特定条件执行求和(SUM)与减法运算,尝试了如下代码:
假设变量$balance的值为655000000(数字中的点仅用于展示,数据库中无此格式),my_table中的数据为IDR 80000000、USD 500000:
$currency_id = 1; $balance = 655.000.000; DB::table('my_table as a') ->join('master_currencies as b', 'a.master_currency_id', 'b.id') ->where('a.id', $id) ->selectRaw("SUM( CASE WHEN $currency_id = a.master_currency_id THEN $balance - a.amount ELSE a.amount END) AS net_value, b.symbol, b.id as master_currency_id" ) ->groupBy('b.id') ->get();
预期结果:
[ {"net_value":"575.000.000","symbol":"IDR","master_currency_id":1}, {"net_value":"500.000","symbol":"USD","master_currency_id":2} ]
实际得到的结果:
[ {"net_value":"1.885.000.000","symbol":"IDR","master_currency_id":1}, {"net_value":"500.000","symbol":"USD","master_currency_id":2} ]
注:数字中的点仅用于展示,数据库中未使用该格式。
解决方案
问题根源
核心逻辑错误:原代码对每条匹配目标货币的记录,计算$balance - 单条金额后再求和,这相当于$balance × 记录条数 - SUM(金额),但你实际需要的是$balance - SUM(金额)——用总余额减去该货币的所有记录总额,而非每条记录都用余额去减再累加。
另外,PHP里$balance = 655.000.000;是语法错误,多个小数点的写法不合法,会导致PHP错误解析数值,进一步引发结果异常。
修正后的代码
调整逻辑顺序,先按货币分组求和,再根据是否是目标货币执行减法,同时用参数绑定避免SQL注入和数值解析问题:
$currency_id = 1; $balance = 655000000; // 正确的数值写法,无多余小数点 DB::table('my_table as a') ->join('master_currencies as b', 'a.master_currency_id', 'b.id') ->where('a.id', $id) ->selectRaw(" CASE WHEN ? = b.id THEN ? - SUM(a.amount) ELSE SUM(a.amount) END AS net_value, b.symbol, b.id as master_currency_id", [$currency_id, $balance] ) ->groupBy('b.id', 'b.symbol') // 非聚合字段必须加入GROUP BY,符合SQL规范 ->get();
关键改动说明
- 逻辑调整:把
SUM移到CASE内部,先计算每个货币的总金额,再针对目标货币做余额减总额的运算,其他货币直接取总额。 - 参数绑定:用
?占位符传递变量,避免直接拼接SQL导致的安全问题和数值格式错误。 - GROUP BY规范:将
b.symbol加入分组字段,避免因MySQL严格模式导致的报错。
这样修改后,就能得到预期结果:IDR的net_value为655000000 - 80000000 = 575000000,USD的net_value保持500000。
内容的提问来源于stack exchange,提问作者nur rahmad
相关产品推荐
相关产品推荐

