Laravel中如何用whereIn返回包含重复值的查询结果?
如何用whereIn返回包含重复值的查询结果?
这个问题我之前也碰到过!默认的whereIn确实会自动去重,因为SQL本身的WHERE IN逻辑就是匹配存在的记录,不管你传多少个重复的ID,它只会返回一次对应的行。要得到和原数组顺序、重复次数完全一致的结果,这里有两种实用的解决办法:
方法一:先查唯一记录,再映射回原数组(推荐)
这种方法只需要查询一次数据库,效率更高,而且利用Laravel的集合操作就能轻松实现:
$ids = [604, 604, 550]; // 第一步:获取所有唯一ID对应的产品记录,用product_id作为集合的键 $uniqueProducts = Parent_product::select('name', 'product_id') ->whereIn('product_id', array_unique($ids)) ->get() ->keyBy('product_id'); // 第二步:遍历原ID数组,把每个ID对应的产品记录映射出来 $result = array_map(function($id) use ($uniqueProducts) { // 可选:确保ID存在,避免报错 if (!$uniqueProducts->has($id)) { return null; // 或者返回你需要的默认值 } return $uniqueProducts->get($id)->toArray(); }, $ids);
执行后$result就是你要的结果:
[ ["name" => "Tomato", "product_id" => 604], ["name" => "Tomato", "product_id" => 604], ["name" => "Patato", "product_id" => 550] ]
方法二:用SQL JOIN实现重复行返回
如果一定要在SQL层面直接获取重复结果,可以通过构造临时数据集和原表JOIN的方式实现。注意不同数据库的语法略有差异:
适用于MySQL 8.0+(支持VALUES语法)
$ids = [604, 604, 550]; // 把ID数组转换成VALUES语法的格式:(604),(604),(550) $idValues = collect($ids)->map(fn($id) => "($id)")->implode(','); $result = Parent_product::select('pp.name', 'pp.product_id') ->join(DB::raw("(VALUES $idValues) AS tmp(id)"), 'pp.product_id', '=', 'tmp.id') ->get() ->toArray();
适用于低版本MySQL或其他数据库(用UNION ALL构造临时表)
$ids = [604, 604, 550]; // 把ID数组转换成UNION ALL的查询语句:SELECT 604 AS id UNION ALL SELECT 604 AS id... $idUnion = collect($ids)->map(fn($id) => "SELECT $id AS id")->implode(' UNION ALL '); $result = Parent_product::select('pp.name', 'pp.product_id') ->join(DB::raw("($idUnion) AS tmp"), 'pp.product_id', '=', 'tmp.id') ->get() ->toArray();
两种方法对比
- 方法一:性能更优,只查一次数据库,适合大多数场景,尤其是ID数组重复较多的情况。
- 方法二:完全在SQL层处理,适合需要直接从数据库获取重复结果的特殊场景,但要注意数据库版本兼容性。
内容的提问来源于stack exchange,提问作者Nixon Teh
相关产品推荐
相关产品推荐

