【问题标题】:Ordering MySQL results to obey parent/child in Table of Contents排序 MySQL 结果以服从目录中的父/子
【发布时间】:2011-10-20 01:16:55
【问题描述】:

我有一个如下所示的目录表:

  • 身份证
  • Parent_ID
  • 章节
  • Display_Order

因此,每一行都是一个章节标题,但章节中可以有章节,章节中也可以有章节。因此,上表允许我维持这些关系。

如果一个章节没有父章节,即它不是任何其他章节的子章节,则 Parent_ID 为“Null”。如果一个章节确实有父章节,则它的 Parent_ID 设置为父章节的 ID。

由于一个章节内可以有多个子章节,这些子章节的顺序通过Display_Order 列进行管理; 1是第一,等等。

谁能建议一个简洁的 SQL 查询,让我可以选择整个表,并产生上述结果?本质上,我正在寻找一个反映章节实际层次结构的结果集。 ASCII 目录如下!

Chapter
-- Chapter
---- Chapter
---- Chapter
---- Chapter
-- Chapter
---- Chapter
---- Chapter
Chapter
Chapter

等等

【问题讨论】:

  • 关卡数量是否已知?
  • 单个查询只能返回 Display_Order 中的所有结果。然后你只需要遍历结果并根据他们的父母来识别它们吗?如果你不能让它工作,可能会查看邻接列表模型:sitepoint.com/hierarchical-data-database
  • 更好的是那篇文章下一页提到的“修改的预排序树遍历”方法。这种方法允许他在一个简单的查询中获得完整的层次结构。 sitepoint.com/hierarchical-data-database-2
  • @Lumbendil 级别数未知,也无法固定,因为目录需要非常灵活。

标签: php mysql hierarchical-data tableofcontents


【解决方案1】:

您不能只使用 SQL 查询来做到这一点(至少在 MySQL 中)。使用 SQL 和 PHP 的方法之一如下:

SELECT id, IFNULL(parent_id, 0) AS parentid, chapter FROM toc ORDER BY parentid, display_order

然后你将这个行集读取到一个数组 $a 中,如下所示:

while ($row = mysql_fetch_array($result)) {
    $a[$row['id']]['name'] = $row['chapter'];
    $a[$row['parentid']]['children'][] = $row['id'];
}

它将创建一个第一个索引为 0 的虚构元素。

打印给定级别的缩进的小示例函数(您可以使用带填充的 CSS 代替 或任何其他方式来生成缩进):

function printIndent($level = 0) {
    for ($j = 0; $j <= $level; $j++) echo '&nbsp';
}

然后你创建一个递归函数 printTree 输出树:

function printTree($key = 0, $level = 0) {
    if ($key > 0) {
         printIndent($level);
         echo $a[$key]['name'];
    }
    if (count($a[$key]['children'])
        foreach ($a[$key]['children'] as $child)
             printTree($child, $level + 1);
}

然后你调用它一次:

printTree();

就是这样。请注意我跳过了数组初始化并且我没有运行这个示例代码,所以它可能有语法错误,但原理就是这个。

这种方法的缺点是,如果您有非常多的项目,那么它不是最有效的,因为您首先将所有内容一次读取到一个大数组中。但对于较少数量的项目,这是一个很好的解决方案。

【讨论】:

  • 忘了补充一点,这个 SQL 查询的 ORDER BY 非常重要,因为数组的生成方式依赖于这一点:父母在他们的孩子之前被迭代。当然,它会考虑同一个父级的子级的显示顺序。
  • 非常感谢。我同意,它不是大规模可扩展的,但它是向前迈出的一大步——这确实是为了证明现阶段的一个观点,如果我们开始处理大量数据,我可能希望转向支持递归的数据库。跨度>
猜你喜欢
  • 2013-03-06
  • 1970-01-01
  • 1970-01-01
  • 2013-12-18
  • 1970-01-01
  • 1970-01-01
  • 2018-07-07
  • 2019-04-09
  • 1970-01-01
相关资源
最近更新 更多