我有以下项目表,其中包含一个名称列表,其中地图返回到表格中的父字段 -
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记录的链接。
这可能吗?
答案 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)