Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/laravel/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 如何在查询中最佳地使用orWhere()?_Mysql_Laravel - Fatal编程技术网

Mysql 如何在查询中最佳地使用orWhere()?

Mysql 如何在查询中最佳地使用orWhere()?,mysql,laravel,Mysql,Laravel,我的问题是: $notifications = \App\Notification::query()->where('users_scope', 'customer') ->with('userSeen') ->where(function ($query) use ($user) { $query->where('user_id_to', 20288) ->orWhere(function($q) use ($user) {

我的问题是:

$notifications = \App\Notification::query()->where('users_scope', 'customer')
   ->with('userSeen')
   ->where(function ($query) use ($user) {
    $query->where('user_id_to', 20288)
        ->orWhere(function($q) use ($user) {
            $q->Where('user_id_to', null)
              ->Where(function($q) use ($user) {
                    $q->where('expire_at', null)->where('created_at', '>=', "2020-04-03 04:18:42");
                    $q->orWhere('expire_at', '!=', null)->where('expire_at', '>', Carbon::now());
                });
        });
    })
    ->select([DB::raw('SQL_CALC_FOUND_ROWS *')])->orderBy('id', 'desc')->limit(20)->get();
这里还有关系(用作
with()
):

下面是一个场景:上面的查询获取最近20个用户的通知(最新通知列表)。最近,
通知
表的大小增加过多。目前它有800多万行。而查询的执行时间超过10秒

注意,在这两个表(
notifications
userSeen
表)上也创建了所有需要的索引。此外,该关系(
userSeen
)类似于一个透视表,指示用户是否已看到通知

你知道我该如何重写该查询以使其更优化吗


关于逻辑的解释:

  • 20288
    是硬编码的,实际上将是
    $user->id
  • user\u id\u to
    null
    时,表示它是批量通知(必须对所有用户可见)
  • 如果用户在处创建的
    值大于用户在
    处创建的
    值,则用户可以看到批量通知
  • 有时,批量通知有一个过期时间(如营销活动),如果仍未过期,则必须向用户显示该时间

我不确定你们有什么条件,但你们可以像下面这样申请

$notifications = \App\Notification::query()->where('users_scope', 'customer')
        ->with('userSeen')
        ->where(function ($query) use ($user) {
            $query->where('user_id_to', 20288);
                if($user){
                    $query->orWhere(function($q) use ($user) {
                        $q->Where('user_id_to', null)
                            ->Where(function($q) use ($user) {
                                $q->where('expire_at', null)->where('created_at', '>=', "2020-04-03 04:18:42");
                                $q->orWhere('expire_at', '!=', null)->where('expire_at', '>', Carbon::now());
                            });
                    });
                }

        })
        ->select([DB::raw('SQL_CALC_FOUND_ROWS *')])->orderBy('id', 'desc')->limit(20)->get();
甚至可以使用when子句
参考:

根据您在问题中提到的逻辑,这应该可以满足您的需要,但是,它可能对速度没有多大帮助:

$notifications = \App\Notification::query()
    ->select([DB::raw('SQL_CALC_FOUND_ROWS *')])
    ->with('userSeen')
    ->where('users_scope', 'customer')
    ->where(function ($query) use ($user) {
        $query
            ->where('user_id_to', $user->id)
            ->orWhere(function ($query) use ($user) {
                $query
                    ->whereNull('user_id_to')
                    ->where('created_at', '>=', $user->created_at)
                    ->where(function ($query) {
                        $query->whereNull('expire_at')->orWhere('expire_at', '>=', now());
                    });
            });
    })
    ->orderByDesc('id')
    ->limit(20)
    ->get();

我还建议尝试两个单独的查询,而不是使用
SQL\u CALC\u FOUND\u ROWS
。以下是几篇解释原因的SO帖子:


然后,您的查询将类似于:

$query = \App\Notification::query()
    ->with('userSeen')
    ->where('users_scope', 'customer')
    ->where(function ($query) use ($user) {
        $query
            ->where('user_id_to', $user->id)
            ->orWhere(function ($query) use ($user) {
                $query
                    ->whereNull('user_id_to')
                    ->where('created_at', '>=', $user->created_at)
                    ->where(function ($query) {
                        $query->whereNull('expire_at')->orWhere('expire_at', '>=', now());
                    });
            });
    })
    ->orderByDesc('id');

$count = $query->count();
$notifications = $query->limit(20)->get();

或者,您可以使用这样的内容。

请您对
$user
逻辑的周围添加一点解释,即
20288
是硬编码还是应该是
$user->id
,用户位的
空值是如何工作的,在
创建的
的哪些位在
/
到期时要分组?哦,你说得对@Rwd。。我将补充一些关于逻辑的解释。。
$query = \App\Notification::query()
    ->with('userSeen')
    ->where('users_scope', 'customer')
    ->where(function ($query) use ($user) {
        $query
            ->where('user_id_to', $user->id)
            ->orWhere(function ($query) use ($user) {
                $query
                    ->whereNull('user_id_to')
                    ->where('created_at', '>=', $user->created_at)
                    ->where(function ($query) {
                        $query->whereNull('expire_at')->orWhere('expire_at', '>=', now());
                    });
            });
    })
    ->orderByDesc('id');

$count = $query->count();
$notifications = $query->limit(20)->get();