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

如何在PHP中用PDO通过单条SELECT语句关联父子数据?

嘿,我完全懂你想靠单条SELECT语句+PDO的fetchAll(PDO::FETCH_GROUP)来搞定父子层级数据的需求——毕竟比起先查父级再循环查子级的N+1查询,这种方式高效太多了!

你提到现在用FETCH_GROUP能得到分组结果,但父级都堆在0这个分组里,子级按对应父ID分组,确实这个结构不是我们想要的最终形态。那咱们来调整一下,把它转成父级数据带对应子级列表的结构:

第一步:用单条SQL获取所有数据并分组

先执行这条SQL查询所有数据,同时让PDO按parent_id分组:

// 执行查询,顺便按parent_id和id排序让结果更规整
$stmt = $pdo->query("SELECT * FROM earth ORDER BY parent_id, id");
// 用FETCH_GROUP按parent_id分组,同时用FETCH_ASSOC让结果是关联数组
$groupedData = $stmt->fetchAll(PDO::FETCH_GROUP | PDO::FETCH_ASSOC);

这时候$groupedData的结构是:

  • $groupedData[0]:所有父级数据(parent_id=0的记录)
  • $groupedData[10]:parent_id=10的所有子级(也就是TREES的子项)
  • $groupedData[11]:parent_id=11的所有子级(FLOWERS的子项)

第二步:重组数据为父级带子级的结构

接下来我们把父级和对应的子级整合到一起:

$finalResult = [];
// 遍历所有父级数据
foreach ($groupedData[0] as $parent) {
    $parentId = $parent['id'];
    // 给父级添加children字段,对应它的子级(没有子级就设为空数组)
    $parent['children'] = $groupedData[$parentId] ?? [];
    $finalResult[] = $parent;
}

现在$finalResult里的每个元素就是一个父级对象,自带children字段,里面是它的所有子级数据,完美符合你的需求!

为什么这个方法高效?

  • 只需要一次数据库查询,彻底避免了N+1查询的性能问题
  • PDO的FETCH_GROUP是底层优化过的分组,比自己在PHP里循环分组要快
  • 后续的重组逻辑非常轻量,几乎没什么性能开销

如果你想试试用JOIN的方式,也可以写这样的SQL,但会返回重复的父级数据,需要额外去重处理,反而不如上面的方法简洁:

SELECT p.*, c.id AS child_id, c.title AS child_title
FROM earth p
LEFT JOIN earth c ON p.id = c.parent_id
WHERE p.parent_id = 0
ORDER BY p.id, c.id

但个人还是更推荐先分组再重组的方案,代码可读性和维护性都更好。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 15:53:10