表中的SQL Sever父,子,子关系

时间:2017-01-24 13:35:34

标签: sql sql-server tsql

我有以下项目表,其中包含一个名称列表,其中地图返回到表格中的父字段 -

id  nameVal parentId  
1   A   NULL  
2   B   NULL  
3   C   NULL  
4   D   NULL  
5   E   NULL  
6   A1  1  
7   A2  6  
8   A3  1  
9   A4  7  
10  B1  2  
11  B2  2  

距离父记录还有一步之遥 - A,A1,A4都是相关的,如下所示......

A1 => A
A2 => A1 => A
A3 => A
A4 => A2 => A1 => A

所以我要做的就是浏览存在关系的所有记录,即A4会带回所有A,因为有原始A记录的链接。

这可能吗?

3 个答案:

答案 0 :(得分:3)

您可以使用递归CTE执行此操作。关键是得到父母。这是一种方法:

with cte as (
      select id, nameval, id as orig
      from t
      where parentid is null
      union all
      select t.nameval, cte.orig
      from cte join
           t
           on t.parentid = cte.id
    )
select cte.*
from cte
where cte.orig = (select cte2.orig from cte cte2 where ct2.nameval = 'A4');

答案 1 :(得分:3)

您可以使用递归查询来获取所有相关行。我不知道数据是否会以你想要的形式存在,因为这个问题似乎有点不清楚。但是例如

获取记录和所有后代:

with r as (
     select *
       from my_table t
      where id = 7
     union all
     select t1.*
       from            my_table t1
            inner join r
                    on t1.parent_id = r.id
)
select * from r;

获取记录和所有祖先:

with r as (
     select *
       from my_table t
      where id = 7
     union all
     select t1.*
       from            my_table t1
            inner join r
                    on t1.id = r.parent_id
)
select * from r;

现在也许你想要孩子和祖先。这可能会有点棘手;递归最好在一条直线上运行,因此不会有无限循环。一种方法是将上述两个查询结合在一起。如果您的真实查询具有您不想写两次的复杂逻辑,那么您可以使用它来获取ID列表,然后通过select ... where id in (my_list)类型查询运行真实查询。

另一个考虑因素是记录是否可以有多个孩子。如果我们有

A
A1 => A
A10 => A1
A11 => A1
A2 => A
A20 => A2
A21 => A2

你可以说这些都是相关的(通过A;有些是“表兄弟”)。因此,如果您从A1搜索并联合前两个示例查询,您将获得A, A1, A10, A11 ...但是您是否还想要A的其他子项?如果是这样,你可以采取略微不同的方法:

首先,找到最年长的祖先:

with r as (
     select *
       from my_table t
      where id = 7
     union all
     select t1.*
       from            my_table t1
            inner join r
                    on t1.id = r.parent_id
)
select id from r where parent_id is null;

然后针对该ID运行原始的“所有后代”查询。如果你想将它全部放入一个语句中,我认为以下*应该*工作(但我不是我可以测试它的地方):

with ancestors as (
     select *
       from my_table t
      where id = 7
     union all
     select t1.*
       from            my_table t1
            inner join ancestors
                    on t1.id = ancestors.parent_id
) , related as (
     select *
       from ancestors
      where parent_id is null
     union all
     select t1.*
       from            my_table t1
            inner join related
                    on t1.parent_id = related.id
)
select * from related;

答案 2 :(得分:3)

也许不止一点,但请考虑以下几点:

您可以设置顶部节点(null将默认为整个层次结构)

您也可以设置过滤器。对于没有过滤器,单个ID或分隔的ID字符串,这可以为空。

@Filter = '7,10'

<强>返回

enter image description here

现在,如果你设置@Filter = '',你就会得到

enter image description here

如果您设置componentDidMount,则会获得

enter image description here