【问题标题】:Recursive tree traversal with mysql through PHP通过 PHP 使用 mysql 进行递归树遍历
【发布时间】:2012-06-15 04:16:38
【问题描述】:

我正在为一位客户创建一份问卷,该问卷要求按 3 层级别组织问题。我已经成功创建了 U.I.但是,在过去的 3 个小时里,我一直在尝试从数据库中提取数据,以使所有内容都加载到正确的位置。数据库是由客户端组织的,所以我无法控制它:

id    description    parentId    
1      Level 1        0           
2      Level 2        0           
3      Level 1a       1   
4      Level 1b       1 
5      Level 1a1      3      

我在网站上发现了一个与我类似的问题,但是当我尝试它的解决方案时,我得到了以下无限重复:

代码:

function makeList($par_id = 0) {
    //your sql code here
    $result = mysql_query("SELECT * FROM pB_test WHERE parentId = $par_id");
    $pages = mysql_fetch_array( $result );

    if (count($pages)) {
        echo '<ul>';
        foreach ($pages as $page) {
            echo '<li>', $page['description'];
                makeList($page['parentId']);
                echo '</li>';
        }
        echo '</ul>';
    }
}

makeList();

输出:

1
3
5
5
l
l
3
5
5
l
l
3
5
5
l
l
3
5
5
l
l

有谁知道如何解决这个问题以及问题到底是什么?干杯

【问题讨论】:

  • MySQL 不支持递归JOINs,这是您真正需要的,但是如果您知道您只有三个级别并且永远只有三个级别,您可以将表连接到自己三倍

标签: php mysql loops recursion traversal


【解决方案1】:

每次都调用mysql服务器取结果不好

如果您有超过 100 行怎么办?或 200+

使用它只查询一次:

$result = mysql_query("SELECT * FROM test");
$arrs = array();

while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
    $arrs[] = $row;
}

function build_tree($arrs, $parent_id=0, $level=0) {
    foreach ($arrs as $arr) {
        if ($arr['parent_id'] == $parent_id) {
            echo str_repeat("-", $level)." ".$arr['name']."<br />";
            build_tree($arrs, $arr['id'], $level+1);
        }
    }
}

build_tree($arrs);

表格的常见示例

  id    name    parent_id

【讨论】:

  • 您可以将global $arrs;(而不是将其作为参数传递)放在函数内部。它不再是黑匣子,但您将使用更少的内存。也使用 mysqli 代替 mysql。反正我喜欢。
  • 这将始终获取完整的表,可能使用 TB 的 RAM - 不可能获取子树,
  • @EugenRieck,只需将WHERE parent_id=$parent_id 子句添加到您的查询中,并将第二个参数添加到build_tree($arrs, $parent_id) 调用中。很明显它不适合大数据,但你会按照 OP 的要求将 TB 的结果包装在 &lt;ul&gt;&lt;li&gt; 中吗?
  • 没错。我永远不会将 TB 包装到 &lt;ul&gt;&lt;li&gt;,但我会将 TB 放入数据库。这个损坏的代码将始终获取所有行,因此what if you have over 100 rows? or 200+ 的答案很简单:绝对不是这个,因为它会在任何大树上严重损坏。
  • 谢谢@vladkras,到目前为止,这是我找到的最佳解决方案
【解决方案2】:

递归执行:

function printChildQuestions($parentid) {
  $sql="SELECT * FROM pB_test WHERE parentID=$parentid";
  $result=mysql_query($sql);
  $i=0;
  while (true) {
    $row=mysql_fetch_array($result);
    if (!$row) break;
    if ($i==0) echo "<ul>";
    $i=1;
    echo '<li>'.$row['id'].'&nbsp;'.$row['description'].'&nbsp;'.$row['parentId'].'</li>';
    printChildQuestions($row['id']);
  }
  if ($i>0) echo '</ul>';
}

printChildQuestions(0);

【讨论】:

  • 有效!太感谢了!你今天赢得了互联网,伙计!
  • 好的,然后我将如何将数据组织到 div 中,所以说 level1 是所有子级的容器,其中还有另一个 div 容器。那么 level2 是列表中的下一个容器吗?
  • 你得问一个单独的问题:我是 PHP/SQL 人,不是 HTML 人,很抱歉
  • 它应该仍然适用吧?如何拆分它以便每个级别都可以嵌套它自己的 html 标记?如果你做不到也没关系。不过感谢您的帮助!
  • 基本上从我的代码开始:我回显&lt;ul&gt; 你应该回显你的起始HTML,&lt;/ul&gt; 成为你的结束HTML。 &lt;li&gt; ... &lt;/li&gt; 行是您的问题。所以我怀疑它应该像开始 &lt;div class=".."&gt;,结束 &lt;/div&gt; 和中间的格式化问题。
猜你喜欢
  • 2012-06-15
  • 2021-05-04
  • 2012-05-25
  • 2018-07-12
  • 2014-03-11
  • 1970-01-01
  • 1970-01-01
  • 2014-07-15
相关资源
最近更新 更多