如何在 MySQL 中使用 PHP 递归地从子元素为空的祖先中获取值

Posted

技术标签:

【中文标题】如何在 MySQL 中使用 PHP 递归地从子元素为空的祖先中获取值【英文标题】:How to Grab value from ancestors in MySQL where child element is null recursively using PHP 【发布时间】:2013-10-15 19:58:37 【问题描述】:

我不确定这是否完全符合我的措辞,但我们开始吧: 我试图弄清楚如何在 php 中创建一个递归循环,该循环基本上检查子列是否为 null - 如果该子元素列具有 null 值,则它使用父 id 递归地遍历其祖先,直到找到具有该列的值,然后将该父值放入原始子列中。由于我刚开始使用 php,但我对数据库和 mysql 有深入的了解,因此我对此感到非常困惑。任何帮助和代码示例都会很棒。

【问题讨论】:

只是为了确定:您是在描述一个包含 ParentID、ChildID 和 TheThingIWant 列的表吗?并且您要选择 TheThingIWant,或者如果 TheThingIWant 为 null,则从最近的祖先中选择 TheThingIWant? 是的,这基本上就是我想要实现的目标。对不起,如果措辞有点混乱。 【参考方案1】:

关于使用邻接列表模型存储分层数据的警告:它以易于创建和更新表为代价换取了重新获取数据的效率低下。我个人在我的项目中使用了Closure Tables,因为即使弄清楚如何在那里获取数据以及如何更新它们是很疯狂的,但在再次获取数据方面效率要高得多。如果您有 Closure Tables,您可以使用一个查询来获取节点的所有具有信息的父节点的列表,并使用 ORDER BY Distance LIMIT 1 来获取您想要的父节点作为您的答案。使用Nested Sets 也是一种选择,尽管我对它们知之甚少。在继续之前,您应该研究这些并考虑您的选择。

这是您现在拥有的邻接列表:

$target = 4; //whatever ID
$db = new mysqli(HOST, USERNAME, PASSWORD, DATABASE);

if($db->connect_errno > 0)
    die('Unable to connect to database [' . $db->connect_error . ']');

$statement = $db->prepare("SELECT ParentID, Audience FROM things WHERE ChildID = ?");

$audience = NULL;
$ChildID = $target; // starts as same value
while(!isset($audience) || !isset($ChildID))   //This assumes that the top ParentID is null; you might have to adjust it
     $statement->bind_param('i', $ChildID);
     $statement->execute();
     $result = $statement->get_result();
     while($row = $result->fetch_assoc())
         if(!isset($row['Audience']) && !isset($audience)) 
             $ChildID = isset($row['ParentID'])?$row['ParentID']:NULL;
          else 
             $audience = $row['Audience'];
         
     
     $result->free();


if(isset($audience)) 
    if($target == $ChildID)  //it was found on that first try
         echo $audience.' was found for '.$target;
     else 
        $statement = $db->prepare("UPDATE things SET Audience = ? WHERE ChildID = ?");
        $statement->bind_param('si', $audience, $target); 
        $statement->execute();
        echo $audience.' was set for '.$target;
    
 else 
    echo 'No audience was found or set for '.$target;



$db->close();

请注意,bind_param 的第一个参数关心您的绑定对象是什么类型(字符串、整数、小数、blob)。你可能需要查一下。

【讨论】:

【参考方案2】:

请提供示例表/字段。我们无法判断您是指一张桌子还是几张桌子。

您的 php 代码可能看起来像这样(查询内容是伪代码)

function updateChild($ChildID,$ParentID=-1)

    //use mysqlquery or whatever
    if($ParentID==-1)
       select field_value,parent_id from mytable where rowid=$ChildID; 
    else
       select field_value,parent_id from mytable where parentid=$ParentID;
    $candidate_value=$row['field_value'];
    $fallback_parent=$row['parent_id']

    if (  is_null($candidate_value))
        updateChild($ChildID, $fallback_parent)
    else
        update mytable set field_value=$candidate_value where $ChildID=$ChildID   

我们的想法是首先获取当前字段值和 parentID,以防万一。如果结果为空,则再次调用相同的函数,传入子项或 rowid 以及下一个要检查的父项。如果父母证明是好的,它会使用一直传递的子值进行更新。请注意,如果上面的代码在第一次尝试时确实有值,则将使用“自身”更新子值,因此应该通过检查 parentid 是否为 -1 来解决这个问题。

【讨论】:

这将是我们正在浏览的一张表。假设您有一个名为“audience”的列,它可以为空,我们基本上试图用来自父级或祖先的值填充此列,但我们只想为子级填充“audience”列,如果父母或祖先对“观众”有实际价值——这就是我必须有递归代码的原因。 *如果子“audience”列确实有值,我们也不想填充它

以上是关于如何在 MySQL 中使用 PHP 递归地从子元素为空的祖先中获取值的主要内容,如果未能解决你的问题,请参考以下文章

PHP - 当给定子键名时,递归地将每个数组元素的键设置为子元素的值

如何在Java中递归地从N元素集中生成所有k元素子集

如何使用堆栈和队列非递归地生成所有可能的n元素集子集?

如何使用 jQuery 从子元素中获取数据以在 xml api 中查找其他子元素?

Matlab:如何在没有循环或内置函数的情况下递归地获取斐波那契序列中的第 N 个元素

php与mysql表中如何求递归求和汇总?