Laravel whereIn 在每个数组项上都有一个 where 子句
Laravel whereIn with a where clause on each array item
假设我有一个用户对象(它属于 ToMany 组),我正在用他们受人尊敬的 ID 数组做一个 whereIn,如下所示:
whereIn('user_id', $group->users->modelKeys())
但是,我需要设置一个条件,我只根据 group_user 枢轴 table、"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;
仍然想看看是否可以在单个查询中完成,没有数组循环。
您是否考虑过使用 foreach
?
$users = whereIn('user_id', $group->users->modelKeys());
foreach ($users as $user) {
// do your comparison here
}
我想您需要对此查询使用 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");
解决了! foreach 循环方法使调用花费的时间太长。一些查询有超过 100k 的记录返回(这是很多循环)导致服务器挂断。答案部分是 Dharmesh Patel 的第三次编辑方法的巨大帮助。我必须做的唯一不同的事情是为 group_id 添加一个 where 子句。
这是最终查询(returns 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');
假设我有一个用户对象(它属于 ToMany 组),我正在用他们受人尊敬的 ID 数组做一个 whereIn,如下所示:
whereIn('user_id', $group->users->modelKeys())
但是,我需要设置一个条件,我只根据 group_user 枢轴 table、"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;
仍然想看看是否可以在单个查询中完成,没有数组循环。
您是否考虑过使用 foreach
?
$users = whereIn('user_id', $group->users->modelKeys());
foreach ($users as $user) {
// do your comparison here
}
我想您需要对此查询使用 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");
解决了! foreach 循环方法使调用花费的时间太长。一些查询有超过 100k 的记录返回(这是很多循环)导致服务器挂断。答案部分是 Dharmesh Patel 的第三次编辑方法的巨大帮助。我必须做的唯一不同的事情是为 group_id 添加一个 where 子句。
这是最终查询(returns 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');