如何在MySQL中查询父表与子表数据且不重复父表行
获取父子表嵌套结构数据的解决方案
看起来你想要的是父表数据不重复,同时将对应的子表数据嵌套在父表条目里的结果对吧?单纯用SQL没法直接返回这种嵌套数组结构,得结合SQL查询+程序处理两步来实现,下面一步步给你讲:
第一步:编写SQL查询语句
首先用LEFT JOIN关联父子表(如果你的父表可能存在没有子表的情况,用LEFT JOIN能保留这些父表行;如果确定所有父表都有子表,用INNER JOIN也可以),同时按父表id排序,这样同一个父表的子表数据会连在一起,方便后续处理:
SELECT p.id, p.info, p.infotwo, c.n_child FROM parent p LEFT JOIN childs c ON p.id = c.id_pnt ORDER BY p.id;
这个查询返回的是扁平的结果集,对应你提供的示例数据,返回结果会是:
| id | info | infotwo | n_child |
|---|---|---|---|
| 1 | home | big | joan |
| 1 | home | big | luci |
| 2 | work | fat | troy |
| 3 | soft | thin | NULL |
能看到父表id=1的行重复了两次,这是JOIN的正常结果,接下来就需要用程序把这些重复的父表行合并,把子表数据收集起来。
第二步:用程序处理成嵌套数组
以PHP为例(因为你给出的示例是PHP数组格式),我们可以遍历查询结果,把同一个父表的子表数据聚合到对应的父表条目中:
// 假设你已经通过数据库扩展(比如PDO/mysqli)执行了上面的SQL,结果存在$result变量中 $parents = []; $currentParentId = null; $currentParent = []; foreach ($result as $row) { // 遇到新的父表条目时,先把之前的父表数据存入数组 if ($row['id'] !== $currentParentId) { if ($currentParentId !== null) { $parents[] = $currentParent; } // 初始化新的父表数据结构 $currentParent = [ 'info' => $row['info'], 'infotwo' => $row['infotwo'], 'data_child' => [] ]; $currentParentId = $row['id']; } // 如果当前行有子表数据,添加到data_child数组中 if (!empty($row['n_child'])) { $currentParent['data_child'][] = ['n_child' => $row['n_child']]; } } // 别忘了把最后一个父表条目加入数组 if ($currentParentId !== null) { $parents[] = $currentParent; } // 现在$parents就是你想要的嵌套结构了 print_r($parents);
执行这段代码后,你得到的$parents数组结构就和你期望的一致:
Array ( [0] => Array ( [info] => home [infotwo] => big [data_child] => Array ( [0] => Array ( [n_child] => joan ) [1] => Array ( [n_child] => luci ) ) ) [1] => Array ( [info] => work [infotwo] => fat [data_child] => Array ( [0] => Array ( [n_child] => troy ) ) ) [2] => Array ( [info] => soft [infotwo] => thin [data_child] => Array ( ) ) )
核心思路说明
SQL的本质是返回二维表结构,所以JOIN后父表行重复是必然的。我们需要通过程序:
- 跟踪当前处理的父表id
- 遇到新的父表id时,创建新的父表条目
- 把同一个父表id对应的子表数据逐个添加到该父条目的
data_child数组中
不管你用的是PHP、Python、Java还是其他语言,这个核心逻辑都是通用的,只是语法细节不同而已。
内容的提问来源于stack exchange,提问作者Carlos
相关产品推荐
相关产品推荐

