GVKun编程网logo

将efficient/elegant way to parse a flat table into a tree?

23

关于将efficient/elegantwaytoparseaflattableintoatree?的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于Anassociationfromthe

关于将efficient/elegant way to parse a flat table into a tree?的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于An association from the table content refers to an、Angular2:ElementRef nativeElement vs querySelector性能、com.intellij.psi.impl.source.tree.LazyParseableElement的实例源码、com.intellij.psi.impl.source.tree.LazyParseablePsiElement的实例源码等相关知识的信息别忘了在本站进行查找喔。

本文目录一览:

将efficient/elegant way to parse a flat table into a tree?

将efficient/elegant way to parse a flat table into a tree?

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

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] ROOT                          /    \               [1] Node 1          [3] Node 2              /       \                   \    [2] Node 1.1     [6] Node 1.2      [5] Node 2.1          /           [4] Node 1.1.1

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

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

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

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


编辑和添加

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

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

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

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

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

答案1

小编典典

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.nameFROM FlatTable f JOIN ClosureTable a ON (f.id = a.descendant_id)WHERE a.ancestor_id = 1ORDER BY f.name;

来自@Nate的评论:

SELECT f.name, GROUP_CONCAT(b.ancestor_id order by b.path_length desc) AS breadcrumbsFROM 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”进行排序。

An association from the table content refers to an

An association from the table content refers to an

今天 hibernate 报了一个错:An association from the table content refers to an unmapped class:com.blog.content.kind

经查,发现是 content.hbm.xml 里面的 Kind 类全名错了。由于之前改动过数据库表,在 content 表里引入了外键 kind_fk,然后用 myeclipse 自动生成 Content 类和相应的 hbm.xml 文件时,就会出现这样的错误!

Angular2:ElementRef nativeElement vs querySelector性能

Angular2:ElementRef nativeElement vs querySelector性能

有时我必须去找DOM事件列表器

我对querySelector更熟悉,我可以更轻松地使用它.

但是我想知道ElementRef提供什么,哪个更好.

解决方法

ElementRef和Renderer提供了DOM API的一部分的抽象,当没有实际的浏览器DOM可用时,它允许执行一些与DOM相关的操作,就像服务器或WebWorker执行Angular应用程序一样.不使用此抽象可能会阻止您的应用程序使用服务器端呈现或WebWorkers.

com.intellij.psi.impl.source.tree.LazyParseableElement的实例源码

com.intellij.psi.impl.source.tree.LazyParseableElement的实例源码

项目:consulo-xml    文件:XmlASTLazyFactory.java   
@NotNull
@Override
public LazyParseableElement createLazy(ILazyParseableElementType type,CharSequence text) {
  if (type == XML_FILE) {
    return new XmlFileElement(type,text);
  }
  else if (type == DTD_FILE) {
    return new XmlFileElement(type,text);
  }
  else if (type == XHTML_FILE) {
    return new XmlFileElement(type,text);
  }
  else if (type == HTML_FILE) {
    return new HtmlFileElement(text);
  }
  else if (type instanceof TemplateDataElementType) {
    return new XmlFileElement(type,text);
  }
  return null;
}
项目:intellij-ce-playground    文件:MiscpsiTest.java   
public void testDoNotExpandnestedChameleons() throws Exception {
  PsiJavaFile file = (PsiJavaFile)myFixture.addFiletoProject("a.java","class A {{{}}}");
  file.getNode();

  PsiCodeBlock initializer = file.getClasses()[0].getinitializers()[0].getBody();
  assertFalse(assertInstanceOf(initializer.getNode(),LazyParseableElement.class).isParsed());

  PsiCodeBlock nestedBlock = ((PsiBlockStatement)initializer.getStatements()[0]).getCodeBlock();
  assertTrue(assertInstanceOf(initializer.getNode(),LazyParseableElement.class).isParsed());
  assertFalse(assertInstanceOf(nestedBlock.getNode(),LazyParseableElement.class).isParsed());
}
项目:intellij-ce-playground    文件:ASTFactory.java   
@NotNull
public static LazyParseableElement lazy(@NotNull final ILazyParseableElementType type,CharSequence text) {
  final ASTNode node = type.createNode(text);
  if (node != null) return (LazyParseableElement)node;

  if (type == TokenType.CODE_FRAGMENT) {
    return new CodeFragmentElement(null);
  }
  else if (type == TokenType.DUMMY_HOLDER) {
    return new DummyHolderElement(text);
  }

  final LazyParseableElement customLazy = factory(type).createLazy(type,text);
  return customLazy != null ? customLazy : DefaultFactoryHolder.DEFAULT.createLazy(type,text);
}
项目:tools-idea    文件:MiscpsiTest.java   
public void testDoNotExpandnestedChameleons() throws Exception {
  PsiJavaFile file = (PsiJavaFile)myFixture.addFiletoProject("a.java",LazyParseableElement.class).isParsed());
}
项目:intellij-ce-playground    文件:ASTFactory.java   
@Nullable
public LazyParseableElement createLazy(final ILazyParseableElementType type,final CharSequence text) {
  return null;
}
项目:intellij-haxe    文件:HaxeAstFactory.java   
@Nullable
@Override
public LazyParseableElement createLazy(ILazyParseableElementType type,CharSequence text) {
  return super.createLazy(type,text);
}
项目:consulo    文件:ASTLazyFactory.java   
@Nonnull
LazyParseableElement createLazy(final ILazyParseableElementType type,final CharSequence text);
项目:consulo    文件:ASTFactory.java   
@Nonnull
public static LazyParseableElement lazy(@Nonnull final ILazyParseableElementType type,final CharSequence text) {
  return ASTLazyFactory.EP.getValue(type).createLazy(type,text);
}

com.intellij.psi.impl.source.tree.LazyParseablePsiElement的实例源码

com.intellij.psi.impl.source.tree.LazyParseablePsiElement的实例源码

项目:consulo-play    文件:PlayBaseTemplateGroovyExpressionElementType.java   
@Nullable
@Override
public ASTNode createNode(CharSequence text)
{
    return new LazyParseablePsiElement(this,text);
}

我们今天的关于将efficient/elegant way to parse a flat table into a tree?的分享已经告一段落,感谢您的关注,如果您想了解更多关于An association from the table content refers to an、Angular2:ElementRef nativeElement vs querySelector性能、com.intellij.psi.impl.source.tree.LazyParseableElement的实例源码、com.intellij.psi.impl.source.tree.LazyParseablePsiElement的实例源码的相关信息,请在本站查询。

本文标签: