【问题标题】:querying a hierarchical mysql table in php在php中查询分层mysql表
【发布时间】:2020-08-25 20:37:03
【问题描述】:

我有一个表,其中包含 3 列 id,name and parent_id 代表类别。根类别(没有父母的类别)的 parent_id 为 0。所有其他类别的 parent_id 作为其直接父母的 id。类别的深度没有限制,我的意思是一个类别可以比根类别低 3,4 甚至 10 级。我现在需要的是一个 PHP 多维数组,其中包含第一级的所有根类别,然后是下一级的直接子类别,每个子类别在其父类别下,以及它们下的子类别 1水平下降。所以它是一个tree like structure.,树中可以有很多层

我不需要确切的代码,但需要一个想法。一个这样的想法是使用选择查询获取所有根类别,然后为每个根查询触发选择查询以递归地获取其子类别等,但这将是太多的选择查询。

或者如果我知道我的表格最多可以包含 300 行,我该怎么做

$categories=GetResultAsArray(select * from categories);

现在操作内存中的 $categories 数组以获得所需的树。

【问题讨论】:

  • 我认为您的两个想法都很好,并且都受到您拥有的数据行数的限制。性能有多少考虑?考虑缓存结果树?您还可以通过对每个查询进行一次自联接来将 sql 查询的数量减半 - 意思是让所有的父母和他们的孩子都深入一层。
  • 是否需要每次都获取完整的树?
  • @andho 不是每次都完整的树,但是是的,经常需要某个根类别的所有孩子

标签: php mysql recursion hierarchical-data


【解决方案1】:

您是对的,使用带有“parentid”列的解决方案很简单,但它会让您编写递归查询。还有其他几种用于在数据库中存储分层数据的设计,可以让您更有效地进行查询。

见:

【讨论】:

  • 我还要添加一个最令人耳目一新的幻灯片:slideshare.net/billkarwin/sql-antipatterns-strike-back
  • 感谢@andho,“SQL 反模式反击”中有关分层数据的内容是另一个演示文稿“使用 SQL 和 PHP 的分层数据模型”的子集
  • 哈哈,我没想到是你的!
【解决方案2】:

这可能是重复的 (http://stackoverflow.com/questions/8431463/more-efficient-hierarchy-system/8431551) 但这里有一个 sn-p 来查询相邻的树 (parent_id,id,title):

$q = mysql_query("SELECT id, parent_id, name FROM categories");
while ($r = mysql_fetch_row($q)) {
  $names[$r[0]] = $r[2];
  $children[$r[0]][] = $r[1];
 }

function render_select($root=0, $level=-1) {
  global $names, $children;
  if ($root != 0)
    echo '<option>' . strrep(' ', $level) . $names[$root] . '</option>';
  foreach ($children[$root] as $child)
    render_select($child, $level+1);
}

echo '<select>';
render_select();
echo '</select>';

【讨论】:

    【解决方案3】:

    您可以从这个检索 url 及其父级的面包屑路径(无限深度的层次结构)的解决方案中获得启发。

    $q = "SELECT T2.*
        FROM (
        SELECT
            @r AS parent_id,
            (SELECT @r := `parent` 
            FROM `route` WHERE id = parent_id) 
        AS `parent`, @l := @l + 1 AS `depth`
        FROM
            (SELECT @r := $route_id, @l := 0) vars, `route` T3
            WHERE @r <> 0) T1
        JOIN `route` T2
        ON T1.parent_id = T2.id
        ORDER BY T1.`depth` DESC";
    
    if($res = $db->query($q)) {
        if($res = $res->fetchAll(PDO::FETCH_ASSOC)) {
            if($size = sizeof($res) > 0) { 
                
                // push results in breadcrumb items array
                $breadcrumb['items']  = $res;
                $breadcrumb['levels'] = $size;
                
                // retrieve only titles
                $titles = array_column($res, 'title');
    
                // construct html result seperated by '>' or '/'
                $breadcrumb['html']['gt'] = implode(' > ', $titles);
                $breadcrumb['html']['sl'] = implode(' / ', $titles);
            }
        }
    }
    

    完整的get_breadcrumb() 函数在这里可用:https://stackoverflow.com/a/63578607/2282880

    【讨论】:

      猜你喜欢
      • 2020-12-27
      • 1970-01-01
      • 2023-03-26
      • 2011-06-26
      • 2011-08-13
      • 1970-01-01
      • 2015-04-16
      • 1970-01-01
      相关资源
      最近更新 更多