【问题标题】:Parent Child Relationships PHP/MYSQL父子关系 PHP/MYSQL
【发布时间】:2020-12-08 16:26:44
【问题描述】:

我有一张这样的桌子:

  • 身份证
  • 姓名
  • parent_id

然后我想根据它们的 id 选择某些行,所以像这样:

SELECT * 
  FROM TABLE 
 WHERE id IN ('1', '5', '8', '9', '35')  

我想从这个查询中也显示父/子关系,例如:

id   parent  
-----------
1    0  
5    1  
8    0  
9    8  
35   9  

所以最终的输出应该是这样的:

1  
--5  

8   
--9  
 ----35  

我是在mysql之外做这个吗,我试过用数组,但不知道,或者
我是在MYSQL里面做的吗,我也不知道怎么做。

【问题讨论】:

  • MySQL 缺乏分层查询支持(其他数据库——Oracle、SQL Server、PostgreSQL...),他们承认他们的文档中存在缺陷:dev.mysql.com/tech-resources/articles/hierarchical-data.html
  • 问题不在于 MySQL 本身,而在于 SQL 原本不支持递归查询。但是,还有其他树表示(嵌套集、路径)本身支持分层视图。
  • @KingCrunch:Oracle 从 v2 开始支持分层查询,使用其 CONNECT BY 语法。这是 ANSI-99,我相信标准化的递归查询(使用递归 WITH),尽管供应商并未实施整个 ANSI 标准......

标签: php mysql sql hierarchical-data


【解决方案1】:

这是我能够提供的,似乎效果很好。

PS-抱歉格式化,不明白:( (fixed?)

  1. 我从 MYSQL 中获取我的 parent_id 和 id 并将其放入一个数组中,其中数组键是 id,值是父母,因此在 mysql 的 while 循环中,类似这样:$testarray[$id] = $parent_id;
  2. 然后我通过下面的函数运行它,它按照我需要的方式对其进行排序。

    function retrieveSubTree($parent, $myarray) {
        $tempArray = $myarray;
        $array = array();           
        //now we have our top level parent, lets put its children into an array, yea!
        while ($child = array_search($parent, $tempArray)) {
            unset($tempArray[$child]);
            //now lets get all this guys children
            if (in_array($child, $tempArray)) {
                $array[$child] = retrieveSubTree($child, $tempArray);
            } else {
                $array[$child] = true;
            }
        }//end while
        return (!empty($array)) ? $array : false;
    }
    
    function retrieveTree($myarray) {
        $array = array();
        $counter = 0;
        foreach ($myarray as $key => $value) {
            $child = $key;
            $parent = $value;
            //if this child is a parent of somebody else
            if (in_array($child, $myarray) && $parent != '0') {
                while ($myarray[$parent] != '' && $myarray[$parent] != '0') {
                    $newparent = $myarray[$parent];
                    $parent = $newparent;
                }
                if (!array_key_exists($parent, $array)) {
                    $array[$parent] = retrieveSubTree($parent, $myarray);
                }
            } else {
                //now make sure they don't appear as some child
                if (!array_key_exists($parent, $myarray)) {
                    //see if it is a parent of anybody
                    if (in_array($child, $myarray)) {
                        $array[$child] = retrieveSubTree($child, $myarray);
                    } else {
                        $array[$child] = true;
                    }
                }//end if array key
            }//end initial in array
        }//end foreach
        return (!empty($array) ? $array : false);
    } 
    
    $test = array(
        '1'=>'15',
        '2'=>'1',
        '3'=>'1',
        '4'=>'0',
        '5'=>'0',
        '6'=>'4',
        '7'=>'6',
        '8'=>'7',
        '9'=>'2',
        '10'=>'9'
    );
    
    print_r(retrieveTree($test)); 
    

【讨论】:

    【解决方案2】:

    在不改变表结构的情况下,这需要递归,这是 MySQL 不支持的。你必须在其他地方做。您可以在 PHP 中编写一个递归函数来使用,例如,breadth-first search 来构建您的数组。在这里,您似乎使用 0 的 parent_id 来表示顶级对象。您可以搜索结果,并将父项为零的每个对象添加到数组中,这将为您提供一个包含 1 和 8 的数组。然后您可以递归:查找父项为 1 的所有结果,并将其添加为子数组为 1;然后找到父级为 8 的所有结果,并将它们添加为 8 的子数组。继续对每个级别执行此操作,直到结果用完为止。

    正如其他海报所指出的,如果您可以更改表结构,您可以在 MySQL 中本地执行此操作。

    【讨论】:

    • 使用OP描述的当前表结构?
    • 如果 OP 需要另一个表结构 - 它可以是正确答案的一部分。
    猜你喜欢
    • 1970-01-01
    • 2011-01-31
    • 1970-01-01
    • 1970-01-01
    • 2018-10-03
    • 2012-01-27
    • 1970-01-01
    • 1970-01-01
    • 2017-05-19
    相关资源
    最近更新 更多