Laravel查询构建器如何对自定义last_update字段使用where条件筛选
方案1:直接复用计算逻辑做筛选(性能最优)
SQL执行顺序中WHERE子句优先级高于SELECT,你定义的last_update别名无法直接在WHERE中使用。你可以用主流数据库都支持的GREATEST函数(取多个值的最大值)替代原来的CASE语句,代码更简洁,同时直接在whereRaw中复用相同逻辑做筛选:
// 优化SELECT定义 $query->select([ "table1.*", DB::raw("GREATEST(table1.updated_at, table2.updated_at) as last_update") ]); // 直接用相同逻辑做区间筛选,参数绑定避免SQL注入 $query->whereRaw("GREATEST(table1.updated_at, table2.updated_at) >= ?", [$this->since]) ->whereRaw("GREATEST(table1.updated_at, table2.updated_at) <= ?", [$this->till]);
提示:如果table2是左连关联,可能存在
table2.updated_at为null的情况,可以用通用的COALESCE函数处理空值,避免计算结果异常:DB::raw("GREATEST(table1.updated_at, COALESCE(table2.updated_at, table1.updated_at)) as last_update")
方案2:用HAVING子句(避免重复写逻辑)
HAVING子句执行顺序在SELECT之后,可以识别查询中定义的别名,适合不想重复写计算逻辑的场景:
$query->select([ "table1.*", DB::raw("GREATEST(table1.updated_at, table2.updated_at) as last_update") ]) ->having('last_update', '>=', $this->since) ->having('last_update', '<=', $this->till);
注:无GROUP BY的场景下,该写法在MySQL、PostgreSQL等主流数据库都可正常运行。
方案3:修正你原有的查询构造器逻辑
你当前的实现中till区间的逻辑完全错误:last_update <= till等价于两个时间都小于等于till,不是orWhere >= till,修正后可完全不用写原生SQL,兼容性最好:
// last_update >= since:任意一个时间满足即可,原有逻辑正确 $query->where(function ($query) { $query->where("table1.updated_at", '>=', $this->since); $query->orWhere("table2.updated_at", '>=', $this->since); }); // last_update <= till:两个时间都要满足条件,不能用or $query->where(function ($query) { $query->where("table1.updated_at", '<=', $this->till); $query->where("table2.updated_at", '<=', $this->till); });
内容的提问来源于stack exchange,提问作者JanTomczyk
相关产品推荐
相关产品推荐

