我有以下问题:对邻接列表进行映像,这已经过了一个递归 来自像这样的SQL
SELECT * FROM pages as ps ORDER BY COALESCE(child_of,page_id), page_id LIMIT x,y
public static function tree(&$arr, $id = NULL) {
$result = array();
foreach ($arr as $a) {
if ($id == $a['child_of']) {
$a ['children'] = self::tree($arr, $a['page_id']);
$result[] = $a;
}
}
return $result;
}
到目前为止,这么好 - 与另一个“flattener”我正在得到我需要的地方。现在,这是诀窍, 这适用于“分页”结果,并且可能发生的事情(并且它确实发生)是父项可以在一个子集中,而子项在不同的子集中。随着上面的递归是显而易见的 孩子不会在缺少父母的情况下到达树上。
关于如何解决这个问题的任何想法? 非常感谢帮助。
答案 0 :(得分:1)
关系表中的分层数据,我们都不喜欢它吗?
使用您当前的数据库布局,您只能通过始终获取所有节点或执行与嵌套级别一样多的JOINS
来解决您的问题,对所有内容进行正确排序(您的排序方式只会产生这个基本问题) ,你有,不太重要)。
在您提出否之前,您应不这样做。
您拥有的另一种方法是选择一个完全不同的模型来创建层次结构:
见幻灯片48及以下。 here
答案 1 :(得分:1)
一个很好的阅读开始是Hierarchical Data In MySQL (我以前可以在MySQL.com网站上找到,arghh)
读它?
以下是如何使用邻接列表模型完成的。但仅适用于已知固定数量的嵌套 (此示例为四个嵌套级别)。
我会找出哪些网页是根页(树的)。然后只选择那些带有查询的人。将LIMIT x,x
放在此select语句中。
之后,以下语句:(或类似的东西)
string query = "
SELECT t1.name AS lev1, t2.name as lev2, t3.name as lev3, t4.name as lev4
FROM category AS t1
LEFT JOIN category AS t2 ON t2.parent = t1.category_id
LEFT JOIN category AS t3 ON t3.parent = t2.category_id
LEFT JOIN category AS t4 ON t4.parent = t3.category_id
WHERE t1.name IN('ELECTRONICS', '<some other name>');
";
可以返回这样的内容:
+-------------+----------------------+--------------+-------+
| lev1 | lev2 | lev3 | lev4 |
+-------------+----------------------+--------------+-------+
| ELECTRONICS | TELEVISIONS | TUBE | NULL |
| ELECTRONICS | TELEVISIONS | LCD | NULL |
| ELECTRONICS | TELEVISIONS | PLASMA | NULL |
| ELECTRONICS | PORTABLE ELECTRONICS | MP3 PLAYERS | FLASH |
| ELECTRONICS | PORTABLE ELECTRONICS | CD PLAYERS | NULL |
| ELECTRONICS | PORTABLE ELECTRONICS | 2 WAY RADIOS | NULL |
| etc... | etc... | etc... | |
+-------------+----------------------+--------------+-------+
诀窍是在查询的IN()
语句中仅使用限制(或ID,如果需要)的查询的根名称。
这应该表现得相当不错(理论上)。
上述查询的原理也可以用来找出树的根中有多少后代(有一点GROUP BY
和COUNT()
魔法;)此外,你可以找出你的哪些页面是根据这个原则(虽然出于性能原因我会将其保存在tabledata中)
如果您想要动态数量的嵌套 (几乎无限扩展),那么实现nested set将是最佳选择。