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

CakePHP 4.4:如何为患者获取各笔记类型的最新笔记?

解决方案:获取每个患者各NoteType的最新笔记

单个患者的查询实现

针对单个患者,推荐用子查询+关联查询的方式,避免依赖数据库DISTINCT的不同行为,确保稳定获取各笔记类型的最新记录:

// 构建子查询:获取该患者下每个笔记类型的最新日期与笔记ID
$subquery = $this->Patients->Notes->find()
    ->select([
        'Notes.patient_id',
        'Notes.note_type_id',
        'max_date' => $this->Patients->Notes->query()->func()->max('Notes.date'),
        'max_id' => $this->Patients->Notes->query()->func()->max('Notes.id')
    ])
    ->where(['Notes.patient_id' => $targetPatientId])
    ->group(['Notes.patient_id', 'Notes.note_type_id']);

// 主查询:关联子查询获取完整笔记与笔记类型数据
$latestNotes = $this->Patients->Notes->find()
    ->select(['Notes.*', 'NotesTypes.*'])
    ->contain(['NotesTypes'])
    ->innerJoin(
        ['Sub' => $subquery],
        [
            'Notes.patient_id = Sub.patient_id',
            'Notes.note_type_id = Sub.note_type_id',
            'Notes.date = Sub.max_date',
            'Notes.id = Sub.max_id' // 处理同日期多条笔记的冲突
        ]
    )
    ->all();

如果你的数据库支持DISTINCT ON(如PostgreSQL),也可以用更简洁的写法:

$latestNotes = $this->Patients->Notes->find()
    ->where(['patient_id' => $targetPatientId])
    ->select(['Notes.*', 'NotesTypes.*'])
    ->contain(['NotesTypes'])
    ->distinct(['Notes.note_type_id'])
    ->orderDesc(['Notes.date', 'Notes.id'])
    ->all();

批量处理所有患者

若需一次性获取所有患者的各类型最新笔记,只需调整子查询的WHERE条件,再按患者分组整理结果:

// 子查询:获取所有患者下每个笔记类型的最新记录标识
$subquery = $this->Patients->Notes->find()
    ->select([
        'Notes.patient_id',
        'Notes.note_type_id',
        'max_date' => $this->Patients->Notes->query()->func()->max('Notes.date'),
        'max_id' => $this->Patients->Notes->query()->func()->max('Notes.id')
    ])
    ->group(['Notes.patient_id', 'Notes.note_type_id']);

// 主查询关联子查询
$latestNotes = $this->Patients->Notes->find()
    ->select(['Patients.id', 'Patients.name', 'Notes.*', 'NotesTypes.*'])
    ->contain(['Patients', 'NotesTypes'])
    ->innerJoin(
        ['Sub' => $subquery],
        [
            'Notes.patient_id = Sub.patient_id',
            'Notes.note_type_id = Sub.note_type_id',
            'Notes.date = Sub.max_date',
            'Notes.id = Sub.max_id'
        ]
    )
    ->all();

// 整理成按患者ID分组的数组
$groupedResult = [];
foreach ($latestNotes as $note) {
    $groupedResult[$note->patient_id][$note->note_type_id] = $note;
}

CakeBook相关指引要点

  • 关联与Contain用法:确保contain()正确加载关联模型,若使用select()需显式包含关联模型字段,否则会丢失关联数据。
  • 聚合函数与分组:使用func()->max()等聚合函数时,必须搭配group()子句指定分组维度,否则会导致聚合结果错误。
  • 子查询的适用场景:子查询是处理「每组取最新/ oldest记录」这类需求的通用方案,避免依赖数据库特定语法。
  • Limit的误区:直接在关联查询中加limit(1)会限制整个关联结果的总数量,而非每组返回1条,这是很多测试失败的核心原因。

内容的提问来源于stack exchange,提问作者Mirko Pagliai

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 11:22:34