2

我有以下问题:对邻接列表进行成像,它已经通过从这样的 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;
}

到目前为止,一切都很好——有了另一个“扁平化器”,我正在到达我需要的地方。现在,这是诀窍,这适用于“分页”结果,可能发生的事情(确实如此)是父母可以在一个子集中,而孩子可以在不同的子集中。通过上面的递归很明显,孩子不会在缺少父母的情况下到达树。

关于如何解决这个问题的任何想法?非常感谢您的帮助。

4

2 回答 2

1

关系表中的分层数据,我们不是都喜欢吗?

使用您当前的数据库布局,您只能通过始终获取所有节点或执行尽可能多JOINS的嵌套级别来解决您的问题,正确排序所有内容(您的排序方式只会使这个基本问题,你有,少一点重要的)。

在你问之前,,你不应该这样做。

您拥有的另一种方法是选择一个完全不同的模型来创建您的层次结构:

  • 嵌套集
  • 所有节点之间的上升/下降关系。

见幻灯片 48 及以下。在这里

于 2011-07-13T14:21:13.713 回答
1

一个很好的入门读物是MySQL 中的分层数据 (我以前可以在 MySQL.com 网站上找到它,啊)

阅读?

这是使用邻接列表模型的方法。但仅适用于已知固定数量的嵌套 (本示例为四个嵌套级别)

我会找出我的哪些页面是(树的)根页面。然后只选择那些有查询的。将 放入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...       |       |
+-------------+----------------------+--------------+-------+

诀窍是在查询语句中仅使用带有限制的查询的根名称(或 ID,如果需要)IN()

这应该仍然表现得很好(理论上)

上述查询的原理也可用于找出树的根中有多少后代(有点神奇;)此外GROUP BYCOUNT()您可以使用此原理找出您的哪些页面是根(尽管我会出于性能原因将其保存在 tabledata 中)

如果您想要动态数量的嵌套 (几乎无限缩放),那么实现嵌套集将是可行的方法。

于 2011-07-13T16:51:30.133 回答