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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 19:12:18