使用Eloquent实现多ID组合匹配多行数据的查询问题咨询
方案实现说明
两个场景的需求均可实现,以下是对应优化方案:
场景1(refid为逗号拼接字符串存储)
问题说明
原有写法存在两处问题:
- 字段名笔误:表字段为
refid,查询时写的是ref_id whereIn逻辑错误:该方法是匹配字段值等于输入数组中的任意一个,不适用于逗号拼接的字符串匹配场景,且需求是同时包含所有输入id的交集结果,不是并集。
实现代码(Laravel框架)
$idArray = $request->input('search', []); $query = Model::query(); // 循环给每个待匹配id加匹配条件,确保所有id都存在于refid字段中 foreach ($idArray as $singleId) { $query->whereRaw('FIND_IN_SET(?, refid) > 0', [$singleId]); } $productIds = $query->pluck('product_id');
注意事项
逗号拼接字符串的存储方式无法利用索引,数据量超过1万条后查询性能会急剧下降,仅适合小数据量场景使用,更推荐改为场景2的行式存储结构。
场景2(refid为单值行式存储)
问题说明
原有写法缺少having条件,仅分组后无法筛选出同时匹配所有输入id的product_id,会把只匹配到单个id的结果也返回。
实现代码(Laravel框架)
$idArray = $request->input('search', []); $idCount = count($idArray); $productIds = Model::whereIn('refid', $idArray) ->groupBy('product_id') // 筛选出匹配到的不同refid数量等于输入id总数的分组,即同时包含所有输入id ->havingRaw('COUNT(DISTINCT refid) = ?', [$idCount]) ->pluck('product_id');
方案优势
该结构可以给refid和product_id建立联合索引,查询性能远高于场景1,是这类多对多关联场景的标准实现方案。
内容的提问来源于stack exchange,提问作者Ruban S
相关产品推荐
相关产品推荐

