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

Laravel 8中如何用groupBy获取带最新消息的患者列表

解决Laravel按patient_id分组获取患者信息及最新聊天消息的问题

问题原因分析

  • 带groupBy('patient_id')时,MySQL默认仅返回每组的第一条匹配记录,因此你只拿到单条患者数据,但由于关联逻辑正确,最新消息显示正常。
  • 移除groupBy后数据为空,大概率是Eloquent关联定义错误,或是查询时未正确加载关联关系,导致患者信息与聊天消息均无法被获取。

具体解决方案

方案一:子查询+关联表获取分组数据

通过子查询先筛选出每个患者的最新聊天记录时间,再关联聊天表和患者表获取完整数据:

$chatGroups = DB::table('chats')
    // 先分组获取每个患者的最新消息时间
    ->select('patient_id', DB::raw('MAX(created_at) as latest_message_time'))
    ->groupBy('patient_id')
    // 关联子查询拿到对应最新消息的内容
    ->joinSub(function ($query) {
        $query->from('chats')
            ->select('patient_id', 'message', 'created_at')
            ->orderBy('created_at', 'desc');
    }, 'latest_chats', function ($join) {
        $join->on('chats.patient_id', '=', 'latest_chats.patient_id')
             ->on('chats.latest_message_time', '=', 'latest_chats.created_at');
    })
    // 关联患者表获取患者信息
    ->join('patients', 'chats.patient_id', '=', 'patients.id')
    // 选择需要返回的字段
    ->select('patients.*', 'latest_chats.message as latest_message', 'latest_chats.created_at as message_time')
    ->get();

方案二:Eloquent关联+筛选最新消息

先确保Patient模型定义了正确的聊天关联:

// app/Models/Patient.php
public function chats()
{
    return $this->hasMany(Chat::class, 'patient_id');
}

然后通过关联闭包直接获取每个患者的最新一条聊天消息:

$patients = Patient::query()
    ->with(['chats' => function ($query) {
        $query->latest()->take(1); // 只取最新的一条消息
    }])
    ->whereHas('chats') // 仅保留有聊天记录的患者
    ->get()
    ->filter(function ($patient) {
        return $patient->chats->isNotEmpty(); // 过滤掉无有效消息的患者(可选)
    });

这种方式会自动按患者分组,返回每个患者的完整信息及最新聊天消息。

方案三:修正GroupBy逻辑(适配MySQL严格模式)

若坚持使用groupBy,需保证select中的非聚合字段都加入groupBy(或关闭MySQL严格模式),同时正确关联患者表:

$chatGroups = DB::table('chats')
    ->join('patients', 'chats.patient_id', '=', 'patients.id')
    ->select(
        'patients.*',
        'chats.message as latest_message',
        DB::raw('MAX(chats.created_at) as latest_time')
    )
    ->groupBy('patients.id', 'chats.message') // MySQL严格模式下需包含所有非聚合字段
    ->orderBy('latest_time', 'desc')
    ->get();

注:此方案若同一患者存在相同内容的消息,可能出现重复分组,建议优先使用前两种方案。

内容的提问来源于stack exchange,提问作者Sajith Madhubashana

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 04:01:55