【问题标题】:What is the best way to model hierarchical data in SQL?在 SQL 中建模分层数据的最佳方法是什么?
【发布时间】:2020-09-22 20:20:37
【问题描述】:

我有以下形式的关系数据:

Parent ID   ParentName  ParentType  RelatedToID RelatedToName   RelatedType
----------------------------------------------------------------------------
     1      A           Business           2        B           Individual
     1      A           Business           4        D           Business
     1      A           Business           3        C           Business
     1      A           Business           6        F           Business
     1      A           Business           3        C           Business
     1      A           Business           9        I           Business
     1      A           Business           9        I           Business
     1      A           Business           3        C           Business
     1      A           Business          12        L           Business
     1      A           Business           5        E           Business
     2      B           Individual         1        A           Business
     2      B           Individual         3        C           Business
     2      B           Individual         3        C           Business
     2      B           Individual         6        F           Business
     2      B           Individual         3        C           Business
     2      B           Individual         4        D           Business
     2      B           Individual         4        D           Business
     3      C           Business           1        A           Business
     3      C           Business           1        A           Business
     3      C           Business           2        B           Individual
     3      C           Business          10        J           Business
     3      C           Business           6        F           Business
     3      C           Business          14        N           Business
     3      C           Business           4        D           Business
     3      C           Business           7        G           Business
     3      C           Business           1        A           Business
     3      C           Business           2        B           Individual
     4      D           Business           2        B           Individual
     4      D           Business           3        C           Business
     4      D           Business           3        C           Business
     4      D           Business          10        J           Business
     4      D           Business           1        A           Business
     4      D           Business           1        A           Business
     4      D           Business           7        G           Business
     5      E           Business           1        A           Business
     5      E           Business           1        A           Business
     6      F           Business           2        B           Individual
     6      F           Business           1        A           Business
     6      F           Business           3        C           Business
     6      F           Business           3        C           Business
     6      F           Business           1        A           Business
     7      G           Business           3        C           Business
     7      G           Business           4        D           Business
     7      G           Business           3        C           Business
     7      G           Business           3        C           Business
     8      H           Individual         9        I           Business
     8      H           Individual         9        I           Business
     9      I           Business           1        A           Business
     9      I           Business           8        H           Individual
    10      J           Business           3        C           Business
    10      J           Business           3        C           Business
    10      J           Business          13        M           Business
    10      J           Business           3        C           Business
    10      J           Business           4        D           Business
    10      J           Business          11        K           Individual
    11      K           Individual        10        J           Business
    11      K           Individual        13        M           Business
    11      K           Individual        10        J           Business
    11      K           Individual        13        M           Business
    12      L           Business           1        A           Business
    13      M           Business          11        K           Individual
    13      M           Business          10        J           Business

我正在使用 DiagrammeR 根据这些数据制作关系图。我需要在 SQL 中转换这些数据以输入到 graphviz。即:

  • 我的最终表格中的一列以 ParentID“->”RelatedToID 的形式(例如“A->B”)
  • 排除任何多余的反向关系,即 A->B 和 B->A 应简化为 A->B

我愿意在我的数据准备步骤中进入关系树的 5 个级别。最终,上面的这个例子应该简化为:

ReadySet

A->B
A->D
A->C
A->F
A->I
A->L
A->E
B->C
B->F
B->D
C->J
C->F
C->N
C->D
C->G
D->J
D->G
H->I
J->M
J->K
K->M

GraphViz 中的结果:

我的尝试和我的困难:

我从定义 ParentType = 'Individual' 的父母开始 然后我使用自我加入来获得行级别的hagiarchy。

我想要(并且似乎做不到)是生成一个 SQL 表,如果用户选择包含在关系树范围内的名称,该表将生成 ReadySet即如果选择 A 然后 ReadySet 或者如果选择 M 然后 ReadySet...在我的整个数据集中显然有更多的父 ID/名称。

【问题讨论】:

  • 您使用的是什么数据库?你能举一个更具体的例子吗?我不确定if M is selected then ReadySet 是什么意思。连接是双向的吗?
  • SSMS。我所说的选择的意思是,如果用户选择了这棵树中的任何值,那么应该返回整个树,这将由 ReadySet 定义。

标签: sql hierarchy hierarchical-data hierarchical-clustering diagrammer


【解决方案1】:

您需要一个表格来定义节点之间的边及其方向。

create table edges (
  from_id bigint not null references nodes(id),
  to_id bigint not null references nodes(id),
  primary key(from_id, to_id);
);

这里的“节点”是实际保存数据的任何表。

如果关系是两种方式,我们需要行,一种用于 A -> B,一种用于 B -> A。

然后执行recursive CTE 来查找所有匹配的行。

with recursive ready_set as (
  select *
  from edges
  where from_id = ?
  union
  select e.*
  from edges e
  inner join ready_set rs on e.from_id = rs.to_id
)
select *
from ready_set;

联合的第一部分是起始条件,第二部分是与CTE连接的递归。

例如,如果我们这样设置边缘:

1 <-> 2 <-> 3 -> 4
1 <-> 5 <- 6

insert into edges values
  (1, 2), (2, 1),
  (2, 3), (3, 2),
  (3, 4),
  (1, 5), (5, 1),
  (6, 5);

除了 6 之外,所有事物都有一条通往 5 的路径。如果我们要求 5,我们将得到除 6、5 之外的所有边。如果我们要求 4,我们将一无所获,因为4 没有传出连接。

如果我们 select distinct to_id from ready_set; 从 5 开始,我们将只获得节点 ID 1、2、3、4 和 5。没有 6。

Try it.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-21
    • 2020-11-21
    • 1970-01-01
    • 2012-07-03
    • 1970-01-01
    • 1970-01-01
    • 2018-06-07
    • 1970-01-01
    相关资源
    最近更新 更多