Laravel实现总付款大于账单的去重数据筛选
需求说明
实现分期付款表的筛选逻辑,按企业主体(badanusaha_id)维度统计,仅返回总付款金额大于总账单金额的去重结果,预期效果为仅展示符合条件的主体(如示例中PT Mandiri)对应数据。
以下是三种未生效的错误写法:
- 第一种错误写法
$paid_off= Instalments::distinct()->whereRaw('bills >= payments ')->get();
- 第二种错误写法
$paid_off = DB::table('instalments') ->selectRaw('count(*) as badanusaha_id, badanusaha_id') ->where(('Sum(bills )'), '>=', ('Sum([payments][1] )')) ->groupBy('badanusaha_id') ->distinct() ->get();
- 第三种错误写法
$pem1 = Instalments::distinct(DB::raw("CAST(SUM(bills) as int) as pem1")); $pem2 = Instalments::select(DB::raw("CAST(SUM(payments ) as int) as pem2")); if($pem1 >= $pem2){ $paid_off = Instalments::distinct()->select('*')->get(); }
错误原因
- 第一种写法:仅逐行判断单行数据的账单和付款大小,未按主体做金额聚合,无法比对总金额,且未指定去重维度,不符合需求。
- 第二种写法:聚合函数
SUM()的判断不能用普通where(where仅支持聚合前逐行过滤),且字段别名冲突、Sum([payments][1])为语法错误,无该种字段引用格式。 - 第三种写法:仅初始化了查询构造器对象,未执行查询拿到实际聚合值,直接对查询对象做大小比较属于逻辑错误,判断通过后直接查询全表数据也未做对应过滤。
正确实现代码
如果需要直接拿到符合条件的企业主体聚合统计结果:
$paidOffBusiness = Instalments::groupBy('badanusaha_id') ->selectRaw('badanusaha_id, SUM(bills) as total_bills, SUM(payments) as total_payments') ->havingRaw('SUM(payments) > SUM(bills)') ->get();
如果需要拿到符合条件的企业对应的全部分期明细,可先筛出符合条件的企业ID再查询明细:
// 筛出总付款大于总账单的企业ID集合 $qualifiedIds = Instalments::groupBy('badanusaha_id') ->havingRaw('SUM(payments) > SUM(bills)') ->pluck('badanusaha_id'); // 查询对应企业的明细数据,按需去重 $paidOffDetails = Instalments::whereIn('badanusaha_id', $qualifiedIds) ->distinct() ->get();
注意事项
- 聚合函数(
SUM/COUNT/AVG等)的结果过滤必须使用having/havingRaw,不能用普通where。 - 不可直接对查询构造器实例做数值比较,必须调用
get()/pluck()/value()等方法执行查询,拿到实际结果后再做逻辑判断。 distinct()默认对查询返回的所有字段组合去重,若需按指定字段去重要明确传入对应字段参数。
内容的提问来源于stack exchange,提问作者Yudhi Ramadhoni
相关产品推荐
相关产品推荐

