【问题标题】:Laravel whereIn not giving desired resultLaravel whereIn 没有给出想要的结果
【发布时间】:2021-03-02 18:51:50
【问题描述】:

我有以下两张表:

unotes    unote_unit
======    ==========
id        unote_id
notes     unit_id

我正在尝试检索其相关 unit_id 列与输入数组完全匹配的 unotes 行。

所以,我运行以下查询:

$unote = UNote::whereHas('units', function ($query) use ($request) {
        $query->whereIn('units.id', $request->unit_lists);
    })
    ->withCount('units')
    ->having('units_count', '=', $u_list_count)
    ->get()
    ->pluck("id");

但是,上述查询的问题在于,即使它只有一个匹配的unit_id,它也会检索数据。例如我有以下数据集:

unotes //with related unit_id
========
id = 3 //49865, 49866, 49867
id = 4  //49865, 49866

使用上面提到的代码,如果我通过[49866,55555],它应该什么都不返回,但它返回 ids 3 和 4,其中包含一个匹配项,但不是全部。

我在Laracasts 上也发现了类似的问题,但运行查询返回Cardinality violation: 1241 Operand should contain 2 column(s)

$unote = UNote::with('units')
    ->whereHas('units', function ($query) use ($request) {
        $query->selectRaw("count(distinct id)")->whereIn('id', $request->unit_lists);
    }, '=', $u_list_count)
    ->get()
    ->pluck("id");

我也发现了类似的问题here,不过好像太贵了。

下面是开始使用的虚拟 SQL:http://sqlfiddle.com/#!9/c3d1f7/1

【问题讨论】:

    标签: php mysql laravel eloquent query-builder


    【解决方案1】:

    因为whereHas 只是将WHERE EXISTS 子句添加到带有指定过滤器的查询中,所以whereIn 确实会为任何匹配返回true。您可以尝试的一件事是运行原始子查询以获取设备 ID 列表并进行比较。

    $search_ids = [49866, 49865];
    sort($search_ids);
    $search_ids = implode(",", $search_ids);
    
    Unote::select("id")
        ->whereRaw(
            "(SELECT GROUP_CONCAT(unit_id ORDER BY unit_id) FROM unote_unit WHERE unote_id = unotes.id) = ?",
            [$search_ids]
        )
        ->get()
        ->pluck("id");
    

    注意,如果您启用了软删除,您还需要过滤掉子查询中的软删除项。

    【讨论】:

    • 似乎还没有工作,sqlfiddle.com/#!9/c3d1f7/49 在传递时显示两行,[49865, 49866]。实际上,它应该只返回 id 4
    • 对,我忘了你想要完全匹配。因此,将RLIKE 替换为=,并将参数更改为$search_ids
    猜你喜欢
    • 2019-11-27
    • 2021-08-29
    • 1970-01-01
    • 2013-10-26
    • 1970-01-01
    • 2017-08-25
    • 2021-12-10
    • 2018-10-17
    • 1970-01-01
    相关资源
    最近更新 更多