【问题标题】:MySQL SELECT Tree Parent IDsMySQL SELECT 树父 ID
【发布时间】:2011-04-16 17:45:51
【问题描述】:

如何对 SELECT 语句的记录进行排序,以便它们代表一棵有效的树?

我所有的尝试都显示子节点嵌套在错误的父节点下。实现这种排序的最可靠方法是什么?

数据

ID      Parent ID      Title
--------------------------------------------
0       NULL           Root
1       0              Node A
2       0              Node B
3       1              Sub-Node C
4       1              Sub-Node D
5       3              Sub-Node E

输出

ID      Parent ID      Title
--------------------------------------------
0       NULL           Root
1       0              Node A
3       1              Sub-Node C
5       3              Sub-Node E
4       1              Sub-Node D
2       0              Node B

数据可视化

Root
    Node A
        Sub-Node C
            Sub-Node E
        Sub-Node D
    Node B

【问题讨论】:

  • 虽然下面提供的示例显示了一些非常酷的查询,但我不认为提供可视化是数据层的工作。使用 PHP,您可以更轻松地做到这一点(并且在视觉上更具吸引力)。
  • @Blindy 我同意你的看法。我希望有一种性能有效的方法可以通过简单的查询来检索结果,但看起来不会很容易。想到的唯一解决方案是使用 PHP 将其排序为一系列临时数组。我只需要一个平面数组,但需要一个按邻接排序的数组。
  • 看看这个答案是否相同:stackoverflow.com/a/33699713/5559741

标签: php mysql sorting


【解决方案1】:

您可以使用嵌套集。看看这篇文章:

Managing Hierarchical Data in MySQL

作者描述了在 SQL 中构建层次结构的几种不同方法,并附有示例查询。关于这个主题的阅读非常好!

【讨论】:

  • 我知道这是一个老问题,但仅供将来参考:嵌套集适用于大部分时间都在读取但很少更改(插入、更新、删除)的树结构,因为写入选项嵌套集合中的成本非常高:robsite.net/…
  • 谢谢你,布罗科!我有点同意这个解决方案。随意发布您自己的答案。它本质上是一个物化视图!
【解决方案2】:

按照@Blindy 的建议,我已经用 PHP 实现了这种排序。下面是两个似乎比较容易解决这个问题的函数。

protected function _sort_helper(&$input, &$output, $parent_id) {
    foreach ($input as $key => $item)
        if ($item->parent_id == $parent_id) {
            $output[] = $item;
            unset($input[$key]);

            // Sort nested!!
            $this->_sort_helper(&$input, &$output, $item->id);
        }
}

protected function sort_items_into_tree($items) {
    $tree = array();
    $this->_sort_helper(&$items, &$tree, null);
    return $tree;
}

我很想知道是否有更简单的方法,但这似乎确实有效。

【讨论】:

  • 调用时传递引用已在 php5.4 中删除
  • @RouR 如果我记得这只是意味着您需要更改调用_sort_helper 的方式。而是尝试使用$this->_sort_helper($input, $output, $item->id);$this->_sort_helper($items, $tree, null);。让我知道这是否有帮助,我会相应地更新我的答案:)
【解决方案3】:

MySQL 不支持递归查询

您需要将表的自连接次数与最大层次结构级别一样多,但以这种方式为每个层次结构级别获取一行仍然非常难看。

有关一些想法和示例,请参阅这些帖子:

Category Hierarchy (PHP/MySQL)

how can we write mysql query where parent id have a child id and next time child id is a parent id how can i do?

【讨论】:

    【解决方案4】:

    我刚刚完成了这个递归函数,并认为这是解决问题的一种优雅方式。这是我在进行基本的 SELECT mysql 查询后所做的:

    function orderChildren($data){
        $tree = array();
        foreach($data as $value){
            if($value['parent_id'] == null){  // Values without parents
                $tree[$value['id']] = $this->goodParenting($value, $data);
            }
        }
        return $tree;
    }
    
    private function goodParenting($parent, $childPool){
        foreach($childPool as $child){
            if($parent['id'] == $child['parent_id']){
                $parent['children'][$child['id']] = $this->goodParenting($child, $childPool);
            }
        }
        return $parent;
    }
    

    【讨论】:

      【解决方案5】:

      这是执行 PHP 函数的另一种方法。

      function buildTree() {
        $data = array();
        $pointers = array();
      
        $sql = "SELECT ID,PARENT,TITLE FROM TREE ORDER BY TITLE ASC";
        $res = $this->db->query($sql);
      
        while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
          if(!isset($pointers[$row['ID']])) {
            $pointers[$row['ID']] = $row;
          }
      
          if(!empty($row['PARENT'])) {
            if(!isset($pointers[$row['PARENT']])) {
              $pointers[$row['PARENT']] = $row;
            }
            $pointers[$row['PARENT']][$row['ID']] =  &$pointers[$row['ID']];
          } else {
            $data[$row['ID']] = &$pointers[$row['ID']]; // This is our top level
          }
        }
      
        unset($pointers);
        return $data;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-06-17
        • 2023-03-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-07
        • 2014-06-13
        相关资源
        最近更新 更多