寻找一种存储父-子-孙-子结构的方法

本文关键字:结构 方法 存储 一种 寻找 | 更新日期: 2023-09-27 18:06:35

我需要存储一个结构,其中N个父级将有1到N个子级,每个子级将有1到N个子级。我希望以一种既相对高性能又高度可扩展的方式将其存储在数据库中,而不需要更改数据库模式。

每个父级必须是唯一的,N个父级可以有相同的子级。然而,这个孩子可能会有不同的孩子,这取决于父母。(清澈如泥?)

可能更容易描述为父母,可能有一个男孩,具有某些属性(棕色头发,棕色眼睛)。父母也有一个男孩,但这个孩子有金发和蓝眼睛。我需要以一种规范化的方式存储这些孩子(男性和女性)和每个属性(头发和眼睛的颜色),并以这样一种方式将它们关联起来:当我查询父母时,我可以得到他们所有的孩子和那些孩子的属性。

我已经对SQL中的树结构和层次结构做了一些研究,但是我很难用一种满足我对性能和可扩展性要求的方式来概念化这个特定的场景。子节点和相关属性将定期(如果不是经常)添加。提前感谢。我知道需要澄清。

额外澄清

好吧,看来可能需要一个不同的例子。让我们以汽车为例。

CarA和CarB都有方向盘、发动机和轮胎。卡拉的方向盘上有无线电控制装置。CarB的方向盘没有。CarA有一个六缸马达,CarB有一个八缸马达。我需要用每个特征的属性为每辆车和每个特征之间的关系建模。我帮上忙了吗?-rb

寻找一种存储父-子-孙-子结构的方法

如果这是固定在三层,他们在概念上是不同的(如在你的扩展的例子),那么我认为你是困惑的树的想法,他们是不必要的。只要像处理其他问题一样使用表和关系就可以了。

  • 家长表
  • 一个用于子节点的表(如果它们总是恰好有两个父节点,则父节点可以是字段,否则还需要一个用于关系的表)
  • 一个表用于属性,另一个表用于它和子表之间的多对多关系[或将这些存储在子表中-参见下面DForck42的评论]
当不同层次的节点是"相同的东西"时,

树是必要的。但是它们不太适合sql,所以我不会尝试在它们似乎不需要的地方使用它们。


更新。从你下面的评论中,我认为你是说孩子被分为类或类型,可能的属性取决于孩子的类型,但这些属性的值取决于父母。

在这种情况下,你有一个完全不同的问题,更像是OO继承。我看到的最简单的解决方案是,您可以为每种类型的子节点使用不同的表。然后每个表对不同的属性有不同的列。子表引用父表

,因此您将有一个具有id的父表。然后你可能有一个"admin sites"的子表。子表的每一行将通过ID引用父表,并包含URL、CSS等列。另一个子类型,如"数据库配置页"将在另一个表中,具有不同的属性集。

如果你有共同的属性,那么你可以在每个表中重复它们,或者有一个"超类"表。

像这样的解决方案可能会变得相当复杂,我建议在你更清楚地解释了你想要什么之后再问另一个问题。这里对这些选项有一个很好的解释—http://www.sqlalchemy.org/docs/orm/inheritance.html(忽略与SQLAlchemy相关的部分,只看它们如何以不同的方式使用表来建模继承)。
我看你的问题,你只需要五张表。
 -> Parent
    ParentId, Col1, Col2, Col3
 -> Child
    ChildId, Col1, Col2, Col3
 -> Grandchild
    GrandchildId, Col1, Col2, Col3
 -> ParentToChild
    ParentId, ChildId
 -> ChildToGrandchild
    ChildId, GrandchildId

存储了所有的关系,这将取决于你为你想要的逻辑做约束;有了这个实现,(Parent, Child)和(Child,孙子)可能有N对N的关系。

这是另一种方法。您只需要两张桌子。第一个是存储构成层次结构的所有"对象"(无论它们是什么)的地方:

ObjectID | ObjectName | ...

第二个是关系表:

RelID | ParentID | ChildID

关系表可以包含一个约束,以确保没有对象是多个父对象的子对象,这几乎免费地为您提供了完整性。

现在遍历表以提取层次结构可能会很棘手,但可以使用相对简单的存储过程来完成。首先,所有对象都应该共享同一个表,因此也应该共享相同的惟一id(理想情况下)。其次是DB支持多少层递归。例如,根据我的经验,SQL Server支持的32个级别已经足够了。但是,在代码中而不是在DB中进行遍历可能会降低性能。

还有其他方法可以解决这个问题。如果你在谷歌上搜索database hierarchical data,你会找到一些,包括一两个正式的CS论文。

我以前用过这个方法,我发现它很简单,性能也很好。

以下方法有什么问题:

create Table Persons    {
  PersonID int Primary Key,
  Name  varchar(100),
  MotherID int {Foreign Key},
  FatherID int {Foreign Key}
}
create Table Attributes
{
    PersonID int {Foreign Key},
    AttributeName varchar(10),
    AttributeValue varchar(10)
}

你会得到一个给定的人的孩子的所有属性:

Select
      Persons.Name,
      Attributes.AttributeName,
      Attributes.AttributeValue
From
      Persons
Left Join
      Atttributes
On
     Persons.PersonID = Attributes.PersonID  
Where
     MotherID = @PersonID or FatherID = @PersonID