Laravel Eloquent实现PostgreSQL WITH查询的技术问题
解决方案
在Laravel里可以直接通过查询构建器的with方法定义CTE,不需要绕路用from传查询实例,直接把你已经构建好的查询作为CTE的子查询即可,具体代码如下:
// 构建带左连接和distinct的子查询 $subQuery = Model::query() ->distinct('models.id') ->leftJoin('blah', 'blah.id', '=', 'models.blah_id') ->orderByRaw('models.id, blah.created_at desc'); // 定义CTE并查询 $result = DB::query() ->with('list', function ($query) use ($subQuery) { // 将子查询作为CTE的数据源 $query->fromSub($subQuery, 'list'); }) ->select('*') ->from('list') ->orderBy('created_at', 'desc') ->get();
也可以用更简洁的写法,直接把子查询传入with:
$subQuery = Model::query() ->distinct('models.id') ->leftJoin('blah', 'blah.id', '=', 'models.blah_id') ->orderByRaw('models.id, blah.created_at desc'); $result = DB::query() ->with(['list' => $subQuery]) ->select('*') ->from('list') ->orderBy('created_at', 'desc') ->get();
说明
- 这里用的
with是查询构建器的CTE定义方法(区别于Eloquent关联的with),第一个参数是CTE的名称(比如这里的list),第二个参数用来定义CTE的具体内容。 fromSub方法可以直接把查询构建器实例转换成子查询,无需手动拼接SQL字符串,完美适配你的需求。- 最终的查询逻辑和你想要的SQL结构完全一致:先定义包含左连接和去重的CTE,再从CTE中查询并排序。
内容的提问来源于stack exchange,提问作者Jaquarh
相关产品推荐
相关产品推荐

