You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 19:27:03