程序问答   发布时间:2022-06-02  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了将efficient/elegant way to parse a flat table into a tree?大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决将efficient/elegant way to parse a flat tablE into a tree??

开发过程中遇到将efficient/elegant way to parse a flat tablE into a tree?的问题如何解决?下面主要结合日常开发的经验,给出你关于将efficient/elegant way to parse a flat tablE into a tree?的解决方法建议,希望对你解决将efficient/elegant way to parse a flat tablE into a tree?有所启发或帮助;

WITH REcursIVE myTree AS ( SELECT * FROM myTable WHERE ParentID IS NulL union all SELECT m.* FROM myTable AS m JOIN myTree AS t ON m.ParentID = t.ID ) SELECT * FROM myTree;

我在2017年的演讲Recursive Query Throwdown中测试了MysqL8.0中的递归查询。

以下是我从2008年起的原始答案:

有几种方法可以在关系数据库中存储树状结构的数据。您在示例中显示的内容使用两种方法:

  • (“父”列)和
  • (名称列中的点号)。

另一个解决方案称为 ,它也可以存储在同一表中。有关这些设计的更多信息,请阅读Joe Celko撰写的 “ sql forsmartIEs中的树和层次结构”。

我通常更喜欢一种称为“ (又称“邻接关系”)的设计来存储树状结构的数据。它需要另一个表,但是查询树很容易。

在我的演示文稿“ 使用sqL和php的分层数据模型”以及《SQL反模式:避免数据库编程的陷阱》一书中,我介绍了闭包表。

create table Closuretable (
  ancestor_ID   int nOT NulL REFERENCES Flattable(ID),
  descendant_ID int nOT NulL REFERENCES Flattable(ID),
  PRIMARY KEY (ancestor_ID, descendant_ID)
);

将所有路径存储在“关闭表”中,其中从一个节点到另一个节点都有直接的祖先。为每个节点添加一行以引用自身。例如,使用您在问题中显示的数据集:

INSERT INTO Closuretable (ancestor_ID, descendant_ID) VALUES
  (1,1), (1,2), (1,4), (1,6),
  (2,2), (2,4),
  (3,3), (3,5),
  (4,4),
  (5,5),
  (6,6);

现在您可以像这样从节点1开始获得一棵树:

SELECT f.* 
FROM Flattable f 
  JOIN Closuretable a ON (f.ID = a.descendant_ID)
WHERE a.ancestor_ID = 1;

输出(在MysqL客户端中)如下所示:

+----+
| ID |
+----+
|  1 | 
|  2 | 
|  4 | 
|  6 | 
+----+

换句话说,将节点3和5排除在外,因为它们是单独层次结构的一部分,而不是从节点1派生而来。

回复:e-satis对直系子女(或直系父母)的评论。您可以在中添加一个“path_length”列,Closuretable便更轻松地专门查询直系子代或父代(或任何其他距离)。

INSERT INTO Closuretable (ancestor_ID, descendant_ID, path_length) VALUES
  (1,1,0), (1,2,1), (1,4,2), (1,6,1),
  (2,2,0), (2,4,1),
  (3,3,0), (3,5,1),
  (4,4,0),
  (5,5,0),
  (6,6,0);

然后,您可以在搜索中添加一个词以查询给定节点的直接子代。这些是后代,他们path_length是1。

SELECT f.* 
FROM Flattable f 
  JOIN Closuretable a ON (f.ID = a.descendant_ID)
WHERE a.ancestor_ID = 1
  AND path_length = 1;

+----+
| ID |
+----+
|  2 | 
|  6 | 
+----+

对@ashraf的评论:“如何按名称对整棵树进行排序?”

这是一个查询示例,该查询返回作为节点1的后代的所有节点,将它们连接到包含其他节点属性(例如)的Flattable并按name名称排序。

SELECT f.name
FROM Flattable f 
JOIN Closuretable a ON (f.ID = a.descendant_ID)
WHERE a.ancestor_ID = 1
ORDER BY f.name;

来自@Nate的评论:

SELECT f.name, GROUP_CONCAT(b.ancestor_ID order by b.path_length desc) AS breadcrumbs
FROM Flattable f 
JOIN Closuretable a ON (f.ID = a.descendant_ID) 
JOIN Closuretable b ON (b.descendant_ID = a.descendant_ID) 
WHERE a.ancestor_ID = 1 
GROUP BY a.descendant_ID 
ORDER BY f.name

+------------+-------------+
| name       | breadcrumbs |
+------------+-------------+
| Node 1     | 1           |
| Node 1.1   | 1,2         |
| Node 1.1.1 | 1,2,4       |
| Node 1.2   | 1,6         |
+------------+-------------+

一位用户今天建议进行修改。SO版主批准了该编辑,但我撤消了它。

修改建议上面的最后一个查询中的ORDER BY应该为ORDER BY b.path_length, f.name,以确保顺序与层次结构匹配。但这是行不通的,因为它将在“节点1.2”之后对“节点1.1.1”进行排序。

解决方法

假设您有一个存储有序树层次结构的平面表:

Id   Name         ParentId   Order
 1   'Node 1'            0      10
 2   'Node 1.1'          1      10
 3   'Node 2'            0      20
 4   'Node 1.1.1'        2      10
 5   'Node 2.1'          3      10
 6   'Node 1.2'          1      20

这是一个图,我们在这里[id] Name。根节点0是虚构的。

                       [0]根
                          / \ 
              [1]节点1 [3]节点2
              / \ \
    [2]节点1.1 [6]节点1.2 [5]节点2.1
          /          
 [4]节点1.1.1

您将使用哪种简约方法将其作为正确排序,正确缩进的树输出到HTML(就此而言,还是文本)?

进一步假设您只有基本的数据结构(数组和哈希图),没有带有父/子引用的奇特对象,没有ORM,没有框架,只有两只手。该表表示为结果集,可以随机访问。

可以使用伪代码或简单的英语,这纯粹是一个概念性问题。

额外的问题:是否有一种从根本上更好的方法将这样的树结构存储在RDBMS中?


编辑和添加

要回答一个评论者的问题:根节点不是必需的,因为它永远不会显示。ParentId =
0是表示“这些是顶级”的约定。Order列定义了具有相同父代的节点的排序方式。

我所说的“结果集”可以图片为一个哈希表数组(保留在该术语中)。对于我的示例,本应已经存在。一些答案需要付出额外的努力,然后再进行构建,但这没关系。

这棵树可以任意深。每个节点可以有N个子节点。不过,我并没有真正想到“成千上万的条目”树。

不要将我对节点命名(“节点1.1.1”)的选择误认为是要依赖的东西。这些节点也可以被称为“ Frank”或“
Bob”,不暗示任何命名结构,这仅仅是为了使其可读。

我已经发布了自己的解决方案,因此你们可以将它分解成碎片。

大佬总结

以上是大佬教程为你收集整理的将efficient/elegant way to parse a flat table into a tree?全部内容,希望文章能够帮你解决将efficient/elegant way to parse a flat table into a tree?所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。