Laravel whereIn在每个数组项

时间:2015-07-17 01:55:02

标签: php arrays laravel where-in

假设我有一个用户对象(属于所有组)并且我正在使用他们所尊重的ID数组来执行whereIn,如下所示:

whereIn('user_id', $group->users->modelKeys())

但是,我需要设置一个条件,我只根据group_user数据透视表的条件“created_at”从每个数组项中提取数据(这基本上是该用户被添加到组时的时间戳)

所以我需要这样的东西:

whereIn('user_id', $group->users->modelKeys())->whereRaw('visits.created_at > group_user.created_at')

这不起作用,因为它没有为每个数组项执行whereRaw,但它对整个查询执行一次。我可能需要做类似嵌套whereIn的事情,但不确定是否会解决它。想法?

我现在的完整查询:

     $ids = $group->users->modelKeys();

     return DB::table('visits')->whereIn('user_id', function($query) use ($ids) {
        $query->select('user_id')->from('group_user')->whereIn('group_user.user_id', $ids)->whereRaw('visits.created_at > group_user.created_at');
    })->sum("views");

好吧让它使用嵌套循环工作:

    $visits = DB::table('visits')->whereIn('user_id', $group->users->modelKeys())->get();

    $sum = 0;

    foreach($group->users as $user) {

        foreach($visits as $visit) {

            if($visit->user_id == $user->id) {

                if($visit->created_at >= $user->pivot->created_at) {
                    $sum += $visit->views;
                }
            }
        }

    }

    return $sum;

仍然想知道是否可以在单个查询中执行此操作,而不是数组循环。

3 个答案:

答案 0 :(得分:1)

您是否考虑过使用foreach

$users = whereIn('user_id', $group->users->modelKeys());

foreach ($users as $user) {
  // do your comparison here
}

答案 1 :(得分:1)

我猜你需要在这个查询中使用JOINS,下面的代码可能会指引你:

$ids = $group->users->modelKeys();

return DB::table('visits')->join('group_user', function ($query) use ($ids) {
    $query->on('visits.user_id', '=', 'group_user.user_id')
        ->whereIn('group_user.user_id', $ids)
        ->whereRaw('visits.created_at > group_user.created_at');
})->sum("views");

修改

$ids = $group->users->modelKeys();

return DB::table('visits')->join('group_user', function ($query) use ($ids) {
    $query->on('visits.user_id', '=', 'group_user.user_id');
})->whereIn('group_user.user_id', $ids)
   ->whereRaw('visits.created_at > group_user.created_at')->sum("views");

修改

$ ids = $ group-> users-> modelKeys();

return DB::table('visits')->join('group_user', function ($query) use ($ids) {
    $query->on('visits.user_id', '=', 'group_user.id') // group_user.id from group_user.user_id as per the loop
          ->on('visits.created_at', '>=', 'group_user.created_at');
})->whereIn('group_user.user_id', $ids)
   ->sum("views");

答案 2 :(得分:1)

解决了! foreach循环方法使得调用花费太长时间。有些查询返回了超过100k条记录(循环过多)导致服务器挂起。答案部分得益于Dharmesh Patel的第三次编辑方法。我唯一要做的就是为group_id添加一个where子句。

这是最后的查询(以毫秒为单位返回100k结果查询)

    //Eager loading. Has overhead for large queries
    //$ids = $group->users->modelKeys();

    //No eager loading. More efficient
    $ids = DB::table('group_user')->where('group_id', $group->id)->lists('user_id');

    return DB::table('visits')->join('group_user', function ($query) use ($ids) {
        $query->on('visits.user_id', '=', 'group_user.user_id')->on('visits.created_at', '>=', 'group_user.created_at');
    })->whereIn('group_user.user_id', $ids)->where('group_id', $group->id)->sum('views');