在目录中对 MySQL 结果进行排序以服从父/子

发布于 2024-12-10 12:29:25 字数 558 浏览 2 评论 0原文

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

  • ID
  • Parent_ID
  • Chapter
  • Display_Order

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

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

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

任何人都可以建议一个简洁的 SQL 查询,它允许我选择整个表,并生成执行上述操作的结果吗?本质上,我正在寻找一个反映章节实际层次结构的结果集。 ASCII 目录如下!

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

ETC。

I have a table for a Table of Contents that looks like this:

  • ID
  • Parent_ID
  • Chapter
  • Display_Order

Each row is therefore a chapter heading, but there can be chapters within chapters, within chapters. Therefore the table above allows me to maintain these relationships.

If a Chapter has no parent, i.e. it is not the sub-chapter of any other chapter, Parent_ID is 'Null'. If a chapter does have a parent, it's Parent_ID is set to the parent chapter's ID.

Since there can be multiple sub chapters within a chapter, the order of these sub chapters is managed via the Display_Order column; 1 being first, etc.

Can anyone suggest a neat SQL query that would allow me to select the entire table, and produce a result that does the above? Essentially, I'm looking for a result set that reflects the actual hierarchy of the chapters. ASCII TOC below!

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

etc.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

养猫人 2024-12-17 12:29:25

你不能只用 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 ' ';
}

然后创建一个输出树的递归函数 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();

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

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

You cannot do it only with SQL queries (at least in MySQL). One of the approaches with SQL and PHP is the following:

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

Then you read this rowset to an array $a like this:

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

It will create a fictive element with first index 0.

A small sample function to print the indent for a give level (you could use CSS with padding instead of   or any other means to generate the indent):

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

Then you create a recursive function printTree that outputs the tree:

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);
}

and you call it once with:

printTree();

This is it. Please note I skipped array initialisations and I did not run this sample code, so it might have syntax error but the principle it this one.

The drawback of this approach is that if you have a very large number of items it would not be the most effective as you read everything at once to a large array first. But for smaller number of items it is a good solution.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文