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

关联policy与policy_case表,如何避免父数据重复并嵌套展示子数据

实现policy父表嵌套policy_case子表数据的解决方案

问题背景

需要将policy作为父表、policy_case作为子表,通过policy.id与policy_case.policy_id关联,实现父数据下嵌套展示子数据的结构。现有CodeIgniter关联查询会导致父表字段(如title、description)随子表条数重复,直接循环渲染会重复显示父数据,无法实现嵌套效果。

问题原因

关联查询(JOIN)会生成父表与子表的笛卡尔积结果,每条父数据会和对应子数据一一匹配,因此父表内容会重复出现,次数等于对应子数据的条数。

解决方案

方案一:分步查询(适合数据量较小场景)

先查询所有父表数据,再循环查询每个父数据对应的子表数据,直接构建嵌套结构:

控制器代码

// 查询所有政策数据(可根据open_flg过滤已发布内容)
$this->db->select('id, title, description, open_flg, open_date');
$this->db->from('policy');
$this->db->where('open_flg', 1);
$policies = $this->db->get()->result_array();

// 为每个政策绑定对应的案例数据
foreach ($policies as &$policy) {
    $this->db->select('id as case_id, title as case_title, contents as case_contents, open_flg, open_date');
    $this->db->from('policy_case');
    $this->db->where('policy_id', $policy['id']);
    $this->db->where('open_flg', 1);
    $policy['cases'] = $this->db->get()->result_array();
}

$data['policies'] = $policies;

视图代码

<?php foreach ($policies as $policy) { ?>
    <div class="policy-wrapper">
        <h2><?php echo $policy['title']; ?></h2>
        <p><?php echo $policy['description']; ?></p>
        
        <?php if (!empty($policy['cases'])) { ?>
            <div class="case-list">
                <?php foreach ($policy['cases'] as $case) { ?>
                    <div class="case-item">
                        <h3><?php echo $case['case_title']; ?></h3>
                        <p><?php echo $case['case_contents']; ?></p>
                    </div>
                <?php } ?>
            </div>
        <?php } ?>
    </div>
<?php } ?>

方案二:单查询后整理数组(适合数据量较大场景)

执行一次关联查询后,通过PHP代码将重复的父数据合并,把子数据嵌套到父数据数组中:

控制器代码

// 执行关联查询
$this->db->select('policy.id, policy.title, policy.description, case.id as case_id, case.title as case_title, case.contents as case_contents');
$this->db->from('policy');
$this->db->join('policy_case case', 'case.policy_id = policy.id');
$this->db->where('policy.open_flg', 1);
$this->db->where('case.open_flg', 1);
$rawResult = $this->db->get()->result_array();

// 整理为嵌套结构
$policies = [];
foreach ($rawResult as $item) {
    $policyId = $item['id'];
    // 初始化父数据
    if (!isset($policies[$policyId])) {
        $policies[$policyId] = [
            'id' => $item['id'],
            'title' => $item['title'],
            'description' => $item['description'],
            'cases' => []
        ];
    }
    // 添加子案例数据
    $policies[$policyId]['cases'][] = [
        'case_id' => $item['case_id'],
        'case_title' => $item['case_title'],
        'case_contents' => $item['case_contents']
    ];
}

// 转换为索引数组(适配视图循环)
$data['policies'] = array_values($policies);

视图代码

与方案一的视图代码完全一致。

方案对比

  • 方案一:代码逻辑清晰,易于维护,但会产生N+1次查询(N为父数据条数),数据量大时性能下降明显。
  • 方案二:仅执行1次数据库查询,性能更优,但需要额外的数组处理逻辑,代码复杂度稍高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 11:25:30