在SQL中为分层数据建模的最佳方法是什么?

问题描述

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

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中产生的结果:

enter image description here

我尝试过的事情和我遇到的困难:

我从定义ParentType ='Individual'的父母开始 然后,我使用自我加入来获得行级的层次结构。

我想要(而且似乎做不到)的是,如果用户做出的选择名称包含在关系树的宽度内,则生成一个sql表,该表将产生 ReadySet 例如,如果选择了A,则 ReadySet ;如果选择了M,则 ReadySet …。整个数据集中显然有更多的父ID /名称

解决方法

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

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),3),(3,4),(1,5),(5,(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