Laravel查询同字段不同whereIn条件下的求和差值实现方法
原查询问题排查
- 嵌套
where子句中写selectRaw无效:where子句仅负责筛选行数据,不能定义字段别名,你声明的in、out别名在外部查询中无法被识别。 - 并列
where条件逻辑冲突:两个where是AND关系,相当于要求type同时属于两个无交集的集合,最终匹配到的行数为0,无法得到计算结果。 - 使用SQL保留关键字作为别名:
in是SQL原生保留关键字,直接用作别名会触发语法错误。 - 不必要的
groupBy:查询已经通过where('contact_id',$this->contact->id)固定了唯一的联系人ID,分组不会产生额外作用。
解决方案
方案1:单查询直接计算差值(性能最优)
采用条件聚合逻辑,将分类判断放到SUM函数内部,不需要全局过滤数据,一次查询即可得到结果:
$amount = Transaction::where('contact_id', $this->contact->id) ->where('date', '<', $from) ->selectRaw( "COALESCE(SUM(CASE WHEN type IN ('CreditNote', 'ReceiptVoucher') THEN amount ELSE 0 END), 0) - COALESCE(SUM(CASE WHEN type IN ('DebitNote', 'PaymentVoucher') THEN amount ELSE 0 END), 0) as amount" ) ->value('amount');
方案2:分开查询后手动计算差值(可读性最高)
如果更倾向于拆分逻辑降低维护成本,可以分别统计两类数据的和再做减法,Laravel的sum()方法会自动将空结果转为0,不需要额外处理空值:
// 统计Type A总和 $sumTypeA = Transaction::where('contact_id', $this->contact->id) ->where('date', '<', $from) ->whereIn('type', ['CreditNote','ReceiptVoucher']) ->sum('amount'); // 统计Type B总和 $sumTypeB = Transaction::where('contact_id', $this->contact->id) ->where('date', '<', $from) ->whereIn('type', ['DebitNote','PaymentVoucher']) ->sum('amount'); // 计算差值 $amount = $sumTypeA - $sumTypeB;
内容的提问来源于stack exchange,提问作者Lucid Polygon
相关产品推荐
相关产品推荐

