我正在尝试构建一个请求,该请求返回特定用户 ID 的子集(通过connected_id)的所有用户,这些用户也在一个或多个年龄范围之间(例如“20-30”、“50-60”) 。年龄范围列表通过另一个数组 ($ageRangeTable) 呈现。 ID 为 5 的用户将被忽略。
用户表仅包含出生日期,因此必须动态计算年龄。
这是我到目前为止所得到的,但导出的 SQL 忽略了 OR 部分。 (我现在使用“explode”来分隔最小和最大年龄,因为实际的字符串“x-y”可能很快就会更改为其他内容)。
$ageRangeTable = ['20-30','50-60'];
$result = Users::where('connected_id', Auth::user()->id)
->where('id' , '!=', 5)
->where(
function ($query) use ($ageRangeTable) {
$count = 0;
foreach($ageRangeTable as $agerange){
list($min,$max) = explode( "-", $agerange);
if($count == 0){
$query->where(`TIMESTAMPDIFF( YEAR, 'dateofbirth', CURDATE() )`, `between`, `{$min} AND {$max}`);
}else{
$query->orWhere(`TIMESTAMPDIFF( YEAR, 'dateofbirth', CURDATE() )`, `between`, `{$min} AND {$max}`);
}
$count++;
}
return $query;
}
);
//->get(); don't use this yet as we just want to review SQL for now...
dd($result->toSql());
生成的 SQL 如下所示:
"select * from `users` where `connected_id` = ? and (`id` != ?)"
...忽略所有“或”。我预料到了这个_
"select * from `users` where `connected_id` = ? and (`id` != ?) and ((`TIMESTAMPDIFF( YEAR, 'dateofbirth', CURDATE() )` BETWEEN ? AND ?) OR (`TIMESTAMPDIFF( YEAR, 'dateofbirth', CURDATE() )` BETWEEN ? AND ?))
接下来我可以尝试什么?
您这里有几个问题:
您还可以使用一些小调整来更多地利用 QueryBuilder
whereBetween
进行查询DB::raw
作为列您的查询将如下所示:
$result = Users::where('connected_id', Auth::user()->id)
->where('id', '!=', 5)
->where(
function($query) use ($ageRangeTable) {
$count = 0;
foreach($ageRangeTable as $agerange) {
[$min, $max] = explode("-", $agerange);
if($count == 0) {
$query->whereBetween(DB::raw('TIMESTAMPDIFF( YEAR, `dateofbirth`, CURDATE() )'), [$min, $max]);
} else {
$query->orWhereBetween(DB::raw('TIMESTAMPDIFF( YEAR, `dateofbirth`, CURDATE() )'), [$min, $max]);
}
$count++;
}
return $query;
}
);
尝试使用原始查询 -
whereRaw
$ageRangeTable = ['20-30', '50-60'];
$sqlRaw = [];
foreach ($ageRangeTable as $range) {
[$min, $max] = explode( '-', $range);
$sqlRaw[] = sprintf('YEAR(DATE_SUB(NOW(), INTERVAL TO_DAYS(dateofbirth) DAY)) BETWEEN %d AND %d', $min, $max);
}
$result = Users::query()
->where('connected_id', \Auth::user()->id)
->where('id' , '!=', 5)
->whereRaw(implode(' AND ', $sqlRaw))
->get();