如何在Laravel查询构建器中使用嵌套Select查询?
将PostgreSQL嵌套SQL转换为Laravel查询构建器代码
我需要将以下PostgreSQL SQL查询转换为Laravel查询构建器代码:
SELECT * FROM ( SELECT DISTINCT ON (c.conversation_meta_id) c.conversation_meta_id cmid,c.id, c.created_date,c.message,u.first_name,u.last_name,pr.name AS practice_role FROM dr_iq.oc_conversation_histories ch LEFT JOIN dr_iq.conversation c ON ch.conversation_meta_id = c.conversation_meta_id LEFT JOIN dr_iq.users u on u.id = c.user_id LEFT JOIN dr_iq.user_group ug on ug.user_id = u.id LEFT JOIN dr_iq.practice_roles pr on ug.practice_role_id = pr.id WHERE ch.ref_id = $ref_id GROUP BY c.created_date, c.conversation_meta_id, c.message, u.first_name,u.last_name,pr.name,c.id,ug.group_id ORDER BY c.conversation_meta_id desc, c.id DESC,c.created_date DESC ) converstaionList order by converstaionList.created_date desc limit 50;我已尝试编写如下代码,但不知如何实现嵌套Select查询:
DB::table('dr_iq.oc_conversation_histories ch') ->SELECT('c.conversation_meta_id')->distinct() ->SELECT('c.conversation_meta_id AS cmid','c.id','c.created_date','c.message','u.first_name','u.last_name','pr.name AS practice_role') ->LEFTJOIN ('dr_iq.conversation c', 'ch.conversation_meta_id', '=', 'c.conversation_meta_id') ->LEFTJOIN ('dr_iq.users u', 'u.id', '=', 'c.user_id') ->LEFTJOIN ('dr_iq.user_group ug', 'ug.user_id', '=', 'u.id') ->LEFTJOIN ('dr_iq.practice_roles pr', 'ug.practice_role_id', '=', 'pr.id') ->WHERE('ch.ref_id', 15218) ->GROUP BY('c.created_date', 'c.conversation_meta_id', 'c.message', 'u.first_name', 'u.last_name', 'pr.name', 'c.id', 'ug.group_id') ->ORDER BY('c.conversation_meta_id DESC, c.id DESC, c.created_date DESC') LIMIT (50);
解决方案
Laravel查询构建器支持通过闭包或直接传入子查询实例实现嵌套查询,针对PostgreSQL特有的DISTINCT ON语法,需要用selectRaw手动声明,同时修正原代码里的方法调用规范问题。
完整转换代码如下:
// 构建子查询 $subQuery = DB::table('dr_iq.oc_conversation_histories as ch') ->selectRaw('DISTINCT ON (c.conversation_meta_id) c.conversation_meta_id as cmid, c.id, c.created_date, c.message, u.first_name, u.last_name, pr.name as practice_role') ->leftJoin('dr_iq.conversation as c', 'ch.conversation_meta_id', '=', 'c.conversation_meta_id') ->leftJoin('dr_iq.users as u', 'u.id', '=', 'c.user_id') ->leftJoin('dr_iq.user_group as ug', 'ug.user_id', '=', 'u.id') ->leftJoin('dr_iq.practice_roles as pr', 'ug.practice_role_id', '=', 'pr.id') ->where('ch.ref_id', 15218) ->groupBy( 'c.created_date', 'c.conversation_meta_id', 'c.message', 'u.first_name', 'u.last_name', 'pr.name', 'c.id', 'ug.group_id' ) ->orderBy('c.conversation_meta_id', 'desc') ->orderBy('c.id', 'desc') ->orderBy('c.created_date', 'desc'); // 外层查询:从子查询取结果并二次排序分页 $result = DB::table($subQuery, 'conversationList') ->select('*') ->orderBy('conversationList.created_date', 'desc') ->limit(50) ->get();
关键细节说明:
DISTINCT ON处理:Laravel默认的distinct()方法无法指定特定字段,因此用selectRaw直接写入PostgreSQL的DISTINCT ON语法。- 方法调用规范:查询构建器方法为驼峰式(如
leftJoin而非LEFTJOIN),groupBy和orderBy需传入字段名数组或多个独立参数,不能直接传拼接字符串。 - 子查询复用:将子查询实例作为外层
DB::table()的第一个参数,并指定别名conversationList,后续即可像操作普通表一样执行排序、分页操作。
内容的提问来源于stack exchange,提问作者M Shahbaz
相关产品推荐
相关产品推荐

