Laravel查询构造器基于数量过滤关联销售重复配对(适配yarja Datatable)
问题根因
你此前使用的->having('aQuantity', '>', 'bQuantity')写法不生效,核心原因是Laravel查询构造器的常规having方法会将第三个参数识别为固定字面量值,而非同查询内的字段引用,最终生成的实际SQL条件为 HAVING aQuantity > 'bQuantity'。由于数字型的aQuantity值在字符串字典序比较中远大于以字母b开头的常量字符串,两个反向关联的统计条目都会被命中,无法实现过滤效果。
可适配Yajra DataTable的SQL层实现方案
所有过滤逻辑直接嵌入SQL查询构造器,不依赖PHP层二次过滤,完全兼容Yajra DataTable的分页、统计、排序逻辑,只需将常规having替换为支持原始语句写入的havingRaw方法即可:
DB::table(DB::raw('tenant_db.sales_data as b')) ->selectRaw('a.product_id as product_id, b.product_id as bought_with, count(*) as times_bought_together, SUM(a.qty) AS aQuantity, SUM(b.qty) AS bQuantity') ->join(DB::raw('tenant_db.sales_data as a'), function ($join){ $join->on('a.sale_id', '=', 'b.sale_id'); $join->on('a.product_id', '<>', 'b.product_id'); }) ->groupBy('a.product_id', 'b.product_id') // 直接在SQL层完成两个聚合值的大小比较 ->havingRaw('aQuantity > bQuantity') ->orderBy('times_bought_together', 'DESC') ->get();
效果说明
- 原示例中的两条反向关联数据中,仅保留
aQuantity > bQuantity的条目:也就是product_id=41、bought_with=42的记录(aQuantity=4,bQuantity=3) - 反向的
product_id=42、bought_with=41记录(aQuantity=3,bQuantity=4)会在SQL执行阶段直接被过滤,不会返回给后续的DataTable处理流程 - 如果需要保留聚合值相等的关联记录,只需将
havingRaw内的判断条件改为aQuantity >= bQuantity即可
补充:MySQL语法支持在
HAVING子句中直接引用SELECT阶段定义的字段别名,上述写法无需重复书写SUM(a.qty)、SUM(b.qty)的计算逻辑;如果适配其他不支持别名引用的数据库,可将条件替换为havingRaw('SUM(a.qty) > SUM(b.qty)'),效果完全一致。
内容的提问来源于stack exchange,提问作者Proudje
相关产品推荐
相关产品推荐

