3

我的数据库中有一个表,其中包含许多家谱树。

-----------------------------
- id  name              parent_id
-----------------------------
- 1   grandfather       NULL
- 2   father            1
- 3   uncle             1
- 4   son               2
- 5   brother           2
- 6   cousin's dauther  7
- 7   cousin            8
- 8   auntie            1

问题是由于边缘情况,我无法显示所有名称:

-当我有一个人的 parent_id 大于它的 parent_id 时(见表亲的女儿)

我使用此查询来获取表:

    $sql = "SELECT p1.id, p1.name, p1.parent_id FROM pariente p1 
    ORDER BY p1.parent_id";
    $result = $conn->query($sql);

问题是如果我使用“ORDER BY parent_id”“堂兄的女儿”将不会显示,如果我使用“ORDER BY id”“堂兄”将不会显示。

我使用这个函数将树变成一个数组并绘制它:

        function make_tree($data, $root) {
            $tree = [];
            foreach ($data as $node) {
                insert($tree, $node);
            }

            return $tree;
        }

        function insert(&$root, &$node) {
            if (!$root) {
                $root = $node;
            }
            else if ($root["id"] === $node["parent_id"]) {
                $root["children"][] = $node;
            }
            else if (array_key_exists("children", $root)) {
                foreach ($root["children"] as &$c) {
                    if (insert($c, $node)) {
                        break;
                    }
                }
            }
        }

        function preorder2(&$root) {
            if ($root) {
                echo "<li>";
                echo $root["name"];

                if (array_key_exists("children", $root)) {
                    echo "<ul>";
                    foreach ($root["children"] as $c) {
                        preorder2($c);
                    }
                    echo "</ul>";
                }
                echo "</li>";
            }
        }
    ?>

在我用它来调用函数之后:

<div>

<?php
while( $row = mysqli_fetch_assoc( $result)){
    $resguard[] = $row;
}
    $tree = make_tree($resguard);
    preorder2($tree);
?>
</div>
4

2 回答 2

1

我曾经遇到过类似的问题,这就是我解决它的方法。

  1. 遍历数据集,将每个节点放入数组中,并跟踪您希望成为根节点的节点。

  2. 遍历数组。对于每个 parent_id 不为 null 的节点,通过 id 查找父节点,并将当前节点添加为子节点。构建树时无需使用递归。

于 2018-08-20T21:33:22.660 回答
0

最后我相信我没有得到烤面包机的答案,但它让我思考,我最终解决了问题(仍然使用 ggorlen 显示树的方式)。

首先这是查询:

$sql = "SELECT p1.id, p2.name, p2.id as minor, p2.name FROM pariente p1 INNER JOIN pariente p2 ON p1.id = p2.parent_id ORDER BY p1.id";
$result = $conn->query($sql);

$sql2 = "SELECT p1.id, p1.nombre, p1.padre_id FROM pariente p1 WHERE p1.padre_id IS NULL ORDER BY p1.id";
$raices = $conn->query($sql2);

功能:

        function make_tree($resguardo, $root){
            $tree = [];
            $tree = $root;
            foreach ($resguardo[$root["id"]] as $node) {
                add($tree, $node, $resguardo);
            }
            return $tree;
        }

        function add(&$root, &$children, $resguardo){
            $root["children"][$children["minor"]] = $children;

            $flag= false;
            if (isset($resguardo[$children["minor"]])) {
                $flag = true;
            }

            if ($flag == false){
                return;
            } else {
                foreach ($resguardo[$children["minor"]] as $child) {
                    agregar($root["children"][$children["minor"]], $child, $resguardo);
                }
            }
        }

        function preorder2(&$root) {
            if ($root) {
                echo "<li>";
                echo '<a href="">';
                echo $root["name"];
                echo "</a>";

                if (array_key_exists("children", $root)) {
                    echo "<ul>";
                    foreach ($root["children"] as $c) {
                        preorder2($c);
                    }
                    echo "</ul>";
                }
                echo "</li>";
            }
        }

我在这里称他们为:

while( $row = mysqli_fetch_assoc($result)){
    $resguardo[$row["id"]][] = $row;
}
    while( $root = mysqli_fetch_assoc( $roots)){
    echo '<ul>';
    $tree = make_tree($resguardo, $root);
    preorder2($tree);
    echo "</ul>";
} 

非常感谢你们两个,如果没有你们的帮助,我永远不会解决它。

于 2018-08-25T03:30:21.657 回答