【问题标题】:Somewhat-Hierarchical Data With MySQLMySQL 的分层数据
【发布时间】:2015-01-24 23:45:37
【问题描述】:

我正在为一个工作项目处理一些层次结构的数据,并试图找到一种更有效的方法来处理它,因为我的第一次尝试可能在很多方面都很糟糕。我已经查看了该站点上的许多分层数据问题,因此我知道以我的结构几乎不可能在单个查询中获取信息。

我要查询的表位于 AS/400 上,每个条目都存储单个步骤的单个部分,因此如果我有 PartOne 和三个组件进入其中,则每个条目都有一个条目:

PartOne ComponentOne, PartOne ComponentTwo, PartThree ComponentThree.

重要的是要注意是否有 ComponentOne 的组件,后续行可能包含:

ComponentOne SubComponentOne, ComponentOne SubComponentTwo.  

考虑到这一点,我试图将给定成品部件的所有组件都放在树状结构中,基本上是把所有东西都放入最终产品中。

我无法为此创建一个展平表,因为我要做的是动态生成该展平表。但是,我确实可以访问成品零件列表。所以我现在的算法是这样的

  1. 获取零件编号,当那是创建零件时查询组件表。
  2. 将这些组件和每个查询作为创建的部分并获取它们的组件。
  3. 重复直到查询不返回任何条目。

在这种情况下,这是 7 个查询深度。我想知道外部的任何人都在寻找更好的算法是否对此有意义,而且自从我完成递归以来已经有一段时间了,但这对于递归来说似乎是合理的,至少在创建查询时是这样。考虑创建一个递归函数从每个级别传回查询结果并在其中某处将信息存储在数组/表/数据库条目中是否合理?

【问题讨论】:

  • mysql 不支持递归查询。有一些用时髦的数据结构来伪造它的黑客,但它们变得非常丑陋:mikehillyer.com/articles/managing-hierarchical-data-in-mysql
  • 如果严格使用mysql,可以将这种数据作为json字符串,否则使用no​​sql数据库是更好的选择。
  • 感谢您提供的链接,我将试一试。我已经读过它不支持递归查询,所以我想我更多地询问了比 7 嵌套更好的方法来构建我的非递归查询。当我提到递归时,我更倾向于创建一种递归方法来生成那些非递归查询。

标签: php mysql algorithm recursion


【解决方案1】:

你想要一个 php 中的树形结构吗? 那么下一个代码示例可能会很有趣。

这将为类别表中的记录构建一个树,以 id -1000 作为根元素开始,只使用与您想要的信息深度一样多的查询。

表结构:

TABLE categories (
   id         INT NOT NULL PRIMARY KEY,
   parent_id  INT NULL,
   name       NVARCHAR(40) NOT NULL
)

PHP 代码:

class Bom {
   public $Id;
   public $Name;
   public $Components = array();

   function __construct( $id, $name ) {
      $this->Id = $id;
      $this->Name = $name;
   }
}

$parentIds = array( -1000 );  // List of id's to lookup
$rootBom = new Bom( -1000, 'Root' );
$bomsById[ -1000 ][] = $rootBom;  // For each id there can be multiple instances if we want separate instances of Bom for each time it occurs in the tree
$maxLevel = 0;

while ( count( $parentIds ) > 0 
   && $maxLevel++ < 10
   && $result = $mysqli->query( "SELECT * FROM categories WHERE parent_id IN ( " . implode( ", ", $parentIds ) . " ) ORDER BY name" ) )
{
   $parentIds = array();  // Clear the lookup list
   $newBomsById = array();
   while ( $row = $result->fetch_assoc() )
   {
      $boms = $bomsById[ $row[ 'parent_id' ] ];
      if ( $boms )
      {
         foreach ( $boms as $bomToUpdate )
         {
            $compontentBom = new Bom( $row[ 'id' ], $row[ 'name' ] );

            $bomToUpdate->Components[] = $compontentBom;
            $newBomsById[ $compontentBom->Id ][] = $compontentBom;
         }

         $parentIds[] = $row[ 'id' ];  // Build new list of id's to lookup
      }
   }

   $bomsById = $newBomsById;
}

echo '<!--
' . print_r( $rootBom, true ) . '
-->';

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-28
    • 2023-03-29
    • 2013-06-12
    • 2012-01-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多