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

CodeIgniter多表查询结果优化:合并同一讲师的日程数据

解决CodeIgniter中一对多关联查询的结果嵌套问题

嘿,这个问题我熟!你现在遇到的是关联查询中一对多关系导致的重复父记录问题,想要把同一讲师的多条日程嵌套成子数组,其实可以通过两种常见方式实现,我给你详细说下:

方法一:分两次查询(先查讲师,再查对应日程)

这种方式逻辑清晰,适合数据量不大的场景,先获取所有符合条件的讲师基础信息,再逐个查询他们的日程并嵌套进去:

public function getDocent() {
    $roles = 'Docent';
    
    // 第一步:获取所有符合角色的讲师基础信息
    $docents_query = $this->db->select('id, name, surname')
        ->from('Persons')
        ->where('roles', $roles)
        ->get();
    $docents = $docents_query->result_array();

    // 第二步:遍历每个讲师,查询对应的空闲日程
    foreach ($docents as &$docent) {
        $agenda_query = $this->db->select('date, start_at, end_at')
            ->from('Agenda')
            ->where('docent_id', $docent['id'])
            ->where('free', 'true')
            ->get();
        // 把日程嵌套为子数组
        $docent['agenda'] = $agenda_query->result_array();
    }

    return $docents;
}

注意:如果需要保留没有任何日程的讲师,这里不需要用关联查询,直接分两次查即可,没有日程的讲师agenda字段会是一个空数组。

方法二:一次查询后重组数组(避免N+1查询)

如果讲师数量较多,分两次查询会产生N+1的数据库请求,这时可以先执行一次关联查询,再在PHP里手动重组结果数组:

public function getDocent() {
    $roles = 'Docent';
    
    // 执行关联查询获取所有原始数据
    $query = $this->db->select('Persons.id, Persons.name, Persons.surname, Agenda.date, Agenda.start_at, Agenda.end_at')
        ->from('Persons')
        ->join('Agenda', 'Persons.id = Agenda.docent_id', 'INNER')
        ->where('Agenda.free', 'true')
        ->where('roles', $roles)
        ->get();
    $raw_results = $query->result_array();

    // 初始化重组后的数组
    $formatted_docents = [];

    // 遍历原始数据,按讲师ID分组嵌套日程
    foreach ($raw_results as $row) {
        $docent_id = $row['id'];
        
        // 如果该讲师还没被添加到结果数组,先写入基础信息
        if (!isset($formatted_docents[$docent_id])) {
            $formatted_docents[$docent_id] = [
                'id' => $row['id'],
                'name' => $row['name'],
                'surname' => $row['surname'],
                'agenda' => []
            ];
        }

        // 把当前日程添加到对应讲师的子数组中
        $formatted_docents[$docent_id]['agenda'][] = [
            'date' => $row['date'],
            'start_at' => $row['start_at'],
            'end_at' => $row['end_at']
        ];
    }

    // 将关联数组转为索引数组(符合你想要的数组结构)
    return array_values($formatted_docents);
}

说明:这种方式只需要一次数据库查询,性能更优;如果要保留无日程的讲师,把INNER JOIN改成LEFT JOIN即可,无日程的讲师agenda字段会是空数组。

控制器无需修改

你的控制器代码保持原样就行,返回的结果会自动变成每个讲师对应一条数据,日程嵌套在agenda子数组里,最终只会返回2个元素的数组,完全符合你的需求~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 13:52:48