You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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();

原代码的问题

  1. 循环中每次调用Offerrequest::whereHas都是创建新的查询实例,没有将条件叠加到同一个查询对象上,最终$otherrequests变量未被正确赋值(甚至会报错);
  2. 仅判断了物料包含指定子物料,但未限制子物料的总数,因此会返回包含额外子物料的记录。

内容的提问来源于stack exchange,提问作者Chippy Thomas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 06:03:20