SQL table - PostgreSQL 中的无限层级
Unlimited levels of hierarchy in SQL table - PostgreSQL
我正在寻找一种方法来存储和处理存储在我的数据库中的各种 organisations/entities 无限层次结构。例如,而不是只有一个 parent 和一个 child 组织(例如 2 级层次结构)和 self-join 允许的 one-to-many 关系(例如有另一列称为parent 引用相同 table) 的 ID,我希望能够拥有尽可能多的层次结构和尽可能多的连接。
假设我有一个组织 table 如下所示:
ID
Name
Other Non-related data
1
Test1
NULL
2
Test2
NULL
3
Test3
something
4
Test4
something else
5
Test5
etc
我正在考虑以下解决方案;对于我需要的每个 table,我可以添加另一个名为 originalTable_hierarchy 的 table,它在两列中引用组织 table,并使其看起来像这样:
ID
Parent ID
ChildID
1
1
2
2
2
4
3
3
1
4
3
2
5
2
3
从这个table可以看出1是parent对2,2是parent对4,3是parent对1,3也是parent 到 2, 2 也是 parent 到 3.
我能想到的限制是不具有相同的 ParentID 和 ChildID(例如像 (3,3) 这样的元组)并且不具有将它们按相反顺序排列的记录(例如如果我有(2,3) 元组,我不能也有 (3,2))
对于我以后可能拥有的多个组织和子组织,这是正确的解决方案吗?用户将不得不轻松地来回浏览它们。如果用户决定将一个组织拆分成多个组织,这个解决方案是否足够?在执行此操作而不是传统的 self-join 或某些层次结构级别的一定数量的 table 时,我还应该考虑什么(额外或缺少的津贴)(例如组织 table 和子组织 table)?另外,你能不能对某些记录施加限制,这样就不能再创建某个parent的child了?或者报告原始 parent 的所有 child?
请随时指示在哪里可以阅读更多相关信息。欢迎任何相关资源。
你只需要一个 table 因为 只有一个 parent 和一个 child 允许无限(无论如何理论上)级别层次结构。您可以通过反转关系来做到这一点,以便 Child
引用 Parent
。 (您的 table 有 Parent
引用 Child
)。这导致 child 在任何级别也可以是 parent。这可以根据需要链接。
create table organization ( id integer primary key
, name text
, parent_id integer references organization(id)
, constraint parent_not_self check (parent_id <> id)
) ;
create unique index organization_not__mirrored
on organization( least(id,parent_id), greatest(id,parent_id) );
检查约束首先强制执行限制,然后是唯一索引。
以下查询显示了完整的层次结构,以及完整的路径和级别。
with recursive hier(parent_id, child_id, path, level) as
( select id, parent_id, id::text, 1
from organization
where parent_id is null
union all
select o.id, o.parent_id,h.path || '->' ||o.id::text,h.level+1
from organization o
join hier h
on (o.parent_id = h.parent_id)
)
select * from hier;
参见 demo here。
我正在寻找一种方法来存储和处理存储在我的数据库中的各种 organisations/entities 无限层次结构。例如,而不是只有一个 parent 和一个 child 组织(例如 2 级层次结构)和 self-join 允许的 one-to-many 关系(例如有另一列称为parent 引用相同 table) 的 ID,我希望能够拥有尽可能多的层次结构和尽可能多的连接。
假设我有一个组织 table 如下所示:
ID | Name | Other Non-related data |
---|---|---|
1 | Test1 | NULL |
2 | Test2 | NULL |
3 | Test3 | something |
4 | Test4 | something else |
5 | Test5 | etc |
我正在考虑以下解决方案;对于我需要的每个 table,我可以添加另一个名为 originalTable_hierarchy 的 table,它在两列中引用组织 table,并使其看起来像这样:
ID | Parent ID | ChildID |
---|---|---|
1 | 1 | 2 |
2 | 2 | 4 |
3 | 3 | 1 |
4 | 3 | 2 |
5 | 2 | 3 |
从这个table可以看出1是parent对2,2是parent对4,3是parent对1,3也是parent 到 2, 2 也是 parent 到 3.
我能想到的限制是不具有相同的 ParentID 和 ChildID(例如像 (3,3) 这样的元组)并且不具有将它们按相反顺序排列的记录(例如如果我有(2,3) 元组,我不能也有 (3,2))
对于我以后可能拥有的多个组织和子组织,这是正确的解决方案吗?用户将不得不轻松地来回浏览它们。如果用户决定将一个组织拆分成多个组织,这个解决方案是否足够?在执行此操作而不是传统的 self-join 或某些层次结构级别的一定数量的 table 时,我还应该考虑什么(额外或缺少的津贴)(例如组织 table 和子组织 table)?另外,你能不能对某些记录施加限制,这样就不能再创建某个parent的child了?或者报告原始 parent 的所有 child?
请随时指示在哪里可以阅读更多相关信息。欢迎任何相关资源。
你只需要一个 table 因为 只有一个 parent 和一个 child 允许无限(无论如何理论上)级别层次结构。您可以通过反转关系来做到这一点,以便 Child
引用 Parent
。 (您的 table 有 Parent
引用 Child
)。这导致 child 在任何级别也可以是 parent。这可以根据需要链接。
create table organization ( id integer primary key
, name text
, parent_id integer references organization(id)
, constraint parent_not_self check (parent_id <> id)
) ;
create unique index organization_not__mirrored
on organization( least(id,parent_id), greatest(id,parent_id) );
检查约束首先强制执行限制,然后是唯一索引。
以下查询显示了完整的层次结构,以及完整的路径和级别。
with recursive hier(parent_id, child_id, path, level) as
( select id, parent_id, id::text, 1
from organization
where parent_id is null
union all
select o.id, o.parent_id,h.path || '->' ||o.id::text,h.level+1
from organization o
join hier h
on (o.parent_id = h.parent_id)
)
select * from hier;
参见 demo here。