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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 07:37:40