如何在Lumen中按一对多关系精确匹配子物料数组
解决Lumen中查询恰好拥有指定子物料集合的物料问题
你的需求是获取恰好包含输入数组中所有子物料,且没有其他子物料的物料,原查询只保证了物料包含指定子物料,但没限制总数,所以会返回包含额外子物料的结果。以下是两种可行的实现方式:
方法一:利用关联查询+统计计数
通过whereHas确保每个指定子物料都存在,再用withCount统计关联子物料的总数,确保总数和输入数组长度一致:
$submaterials_array = [12, 13]; $requiredSubCount = count($submaterials_array); $otherrequests = Offerrequest::where(function ($query) use ($submaterials_array) { // 循环确保每个指定子物料都存在关联 foreach ($submaterials_array as $subId) { $query->whereHas('submaterialprops', function ($q) use ($subId) { $q->where('submaterial_id', $subId); }); } }) // 统计当前物料关联的子物料总数 ->withCount('submaterialprops') // 确保子物料总数等于输入数组长度,排除有额外子物料的情况 ->having('submaterialprops_count', '=', $requiredSubCount) ->get();
方法二:关联表分组查询
通过关联子物料表,分组后用having条件同时满足子物料覆盖度和总数要求:
$submaterials_array = [12, 13]; $requiredSubCount = count($submaterials_array); $otherrequests = Offerrequest::join('submaterialprops', 'offerrequests.id', '=', 'submaterialprops.offerrequest_id') // 筛选出关联子物料在指定数组内的记录 ->whereIn('submaterialprops.submaterial_id', $submaterials_array) // 按物料ID分组 ->groupBy('offerrequests.id') // 确保去重后的子物料数量等于输入数组(保证所有指定子物料都存在) ->havingRaw('COUNT(DISTINCT submaterialprops.submaterial_id) = ?', [$requiredSubCount]) // 确保关联的子物料总记录数等于输入数组(避免同一子物料重复关联的情况,若允许重复可去掉此条件) ->havingRaw('COUNT(submaterialprops.id) = ?', [$requiredSubCount]) // 只选择物料表的字段 ->select('offerrequests.*') ->get();
原代码的问题
- 循环中每次调用
Offerrequest::whereHas都是创建新的查询实例,没有将条件叠加到同一个查询对象上,最终$otherrequests变量未被正确赋值(甚至会报错); - 仅判断了物料包含指定子物料,但未限制子物料的总数,因此会返回包含额外子物料的记录。
内容的提问来源于stack exchange,提问作者Chippy Thomas
相关产品推荐
相关产品推荐

