mysql 如何解决Laravel中在本地作用域中使用whereNotIn()时数组大小的限制

7hiiyaii  于 12个月前  发布在  Mysql
关注(0)|答案(2)|浏览(109)

我有一个数组,我用它来过滤出某个查询的结果。有一个已知的问题,当whereNotIn()whereIn()中传递的数组超过一定数量时,查询返回null(我想是+- 1500条记录)。请参阅:链接
我已经读到了一些解决方法,比如使用原始查询或将in_predicate_conversion_threshold设置为0。但我认为原始查询是不可能的,因为它是一个局部范围,并且您在已经存在的查询上构建查询,我觉得将in_predicate_conversion_threshold设置为0是不好的做法,我认为这只在MariaDb数据库中可行(而不是在MySQL中,这是我正在使用的)。而且当这样做时,我得到一个错误,说in_predicate_conversion_threshold是一个未知的系统变量。
现在我认为这个问题的最佳解决方案是将数组分成更小的块,但我不知道如何在局部范围内使用查询来实现这一点。

public function scopeNotBlacklisted(Builder $query): void
{
    $blacklist = Transaction::where('finalized_at', '>=', now()->subDays(365)->toDateString())
        ->pluck('phonenumber')
        ->all();
    $query->whereNotIn('phonenumber', $blacklist);
}

字符串

tcomlyy6

tcomlyy61#

尝试使用左连接,如果连接值为null,则返回结果

public function scopeNotBlacklisted(Builder $query): void {
    $query->leftJoin('transactions as tr', function ( $join ) {
        $join->on('YOUR_WHATEVER_TABLE_HERE.phonenumber', '=', 'tr.phonenumber')
            ->where('tr.finalized_at', '>=', now()->subDays(365)->toDateString());
    })->whereNull('tr.phonenumber');
}

字符串

EDIT-另一种方法,您可以尝试不使用左连接,而是使用>whereNotExists进行原始查询

public function scopeNotBlacklisted(Builder $query): void {
    $query->whereNotExists(function ($sub) {
        $sub->selectRaw('1')
        ->from('transactions as tr')
        ->where('tr.finalized_at', '>=', now()->subDays(365)->toDateString())
        ->whereColumn('tr.phonenumber', '=', 'YOUR_MAIN_TABLE.phonenumber');
    });
}

khbbv19g

khbbv19g2#

您可以在scope中使用array_chunk,如下所示。

public function scopeNotBlacklisted(Builder $query): void
{
    $blacklist = Transaction::where('finalized_at', '>=', now()->subDays(365)->toDateString())
        ->pluck('phonenumber')
        ->all();

    $chunkedBlacklist = array_chunk($blacklist, 500); // you can adjust count here.

   
    collect($chunkedBlacklist)->each(function ($chunk) use ($query) {
        $query->unless(empty($chunk), function ($query) use ($chunk) {
            $query->whereNotIn('phonenumber', $chunk);
        });
    });
}

字符串
处理whereInwhereNotIn子句的大型数据集的另一种选择是使用临时表。

相关问题