Laravel能否根据参数值自动切换column = ?与column IS NULL语法?
解决方案
Laravel 内置的查询构造器已经默认实现了 null 值的自动识别处理,无需手动拼接 SQL 分支和调整参数数组。
推荐方案:使用查询构造器重写逻辑
查询构造器的 where() 方法会自动判断传入的条件值:如果值为 null,会自动生成 IS NULL 语法;如果是普通值,会生成 = ? 占位符并自动绑定参数,完全不需要手动处理分支逻辑,同时还能避免 SQL 注入风险。
示例代码如下:
use Carbon\Carbon; use Illuminate\Support\Facades\DB; $latestSnapshots = DB::table('snapshots') ->selectRaw('MAX(id) AS id, item_id') ->where('taken_at', '>', Carbon::today()->subDays(90)) ->where('cohort_id', $cohortId) // 自动处理null值 ->groupBy('item_id'); $chartData = DB::table('snapshots') ->joinSub($latestSnapshots, 'latest', fn ($join) => $join->on('latest.id', '=', 'snapshots.id')) ->join('items', 'items.id', '=', 'snapshots.item_id') ->select('items.name', 'snapshots.value', 'snapshots.taken_at') ->orderBy('items.slug') // 原SQL中media_items为笔误,已修正为items ->get();
如果你的需求是取每个 item 对应的value最高的快照,只需要把子查询的逻辑调整为按value取最大值对应的ID即可,其余逻辑不需要改动。
备选方案:必须使用原生SQL的优化写法
如果因业务需要必须手写原生SQL,可以用三元表达式简化分支逻辑,避免重复定义公共参数:
use Carbon\Carbon; use Illuminate\Support\Facades\DB; $params = [Carbon::today()->subDays(90)]; $cohortCondition = $cohortId === null ? 'AND snapshots.cohort_id IS NULL' : tap('AND snapshots.cohort_id = ?', function () use (&$params, $cohortId) { $params[] = $cohortId; }); $query = <<<SQL SELECT items.`name`, snapshots.`value`, snapshots.`taken_at` FROM snapshots INNER JOIN ( SELECT MAX(id) AS id, item_id FROM snapshots WHERE `taken_at` > ? {$cohortCondition} GROUP BY item_id ) latest ON latest.`id` = snapshots.`id` INNER JOIN items ON items.`id` = snapshots.`item_id` ORDER BY items.`slug` ASC SQL; $chartData = DB::select($query, $params);
内容的提问来源于stack exchange,提问作者Jon Winstanley
相关产品推荐
相关产品推荐

