Sql 检索给定记录的所有子项和父项
我想检索给定记录的所有父记录,然后获取这些父记录的所有子记录 例如:如果桌子是这样的 表1:Sql 检索给定记录的所有子项和父项,sql,oracle,connect-by,Sql,Oracle,Connect By,我想检索给定记录的所有父记录,然后获取这些父记录的所有子记录 例如:如果桌子是这样的 表1: Child_Id | Parent_Id --------------------- 23 4 23 5 4 20 20 21 5 12 12 15 12 17 24 30
Child_Id | Parent_Id
---------------------
23 4
23 5
4 20
20 21
5 12
12 15
12 17
24 30
39 4
鉴于上面的表格,id是23,那么我必须检索
21
20
4
23 39
15
12
5
23
17
12
5
23
我试着和prior联系,但对我没有帮助
SELECT * FROM TABLE1
CONNECT BY PRIOR CHILD_ID = PARENT_ID
有没有办法先获取给定节点的所有父节点,然后再获取其父节点的所有子节点以及同级节点?您可以使用以下方法获取父节点/根节点的列表:
select parent_id as parent
from tbl x
where not exists (select 1 from tbl y where y.child_id = x.parent_id)
| PARENT |
|--------|
| 15 |
| 21 |
| 17 |
| 30 |
然后,对于给定的根,可以运行以下操作:
select 21 as parent,
listagg(child_id, ' >>> ') within group(order by level) as children
from tbl
start with parent_id = 21
connect by prior child_id = parent_id
| PARENT | CHILDREN |
|--------|------------------------|
| 21 | 20 >>> 4 >>> 23 >>> 39 |
或者,如果您不想将子项放在一行中,您可以通过运行以下命令获得类似于您给出的输出:
select 21 as parent,
lpad(child_id,level*level,' ') as child
from tbl
start with parent_id = 21
connect by prior child_id = parent_id
| PARENT | CHILD |
|--------|-----------|
| 21 | 2 |
| 21 | 4 |
| 21 | 23 |
| 21 | 39 |
我不确定是否要在一个查询中为所有根运行它,但我想我至少会在等待另一个答案时为您提供它
然而,如果每个数据库中总是只有几个孩子(比如10岁以下),那么这应该是可行的,而不需要依赖connectby,而是使用子查询
作为该方法的一个示例,以下内容深入到8个级别,只要子级不超过8个(如果不是这样的话,您可以添加更多子级),就应该适用于整个表:
您使用的是什么版本的Oracle。太糟糕了。Oracle 11g具有递归CTE,我发现它比
connectby
更易于使用。
with lvl1 as
(select x.parent_id, x.child_id
from tbl x
where not exists (select 1 from tbl y where y.child_id = x.parent_id)),
lvl2 as
(select x.parent_id, x.child_id
from tbl x
left join lvl1
on x.parent_id = lvl1.child_id),
lvl3 as
(select x.parent_id, x.child_id
from tbl x
left join lvl2
on x.parent_id = lvl2.child_id),
lvl4 as
(select x.parent_id, x.child_id
from tbl x
left join lvl3
on x.parent_id = lvl3.child_id),
lvl5 as
(select x.parent_id, x.child_id
from tbl x
left join lvl4
on x.parent_id = lvl4.child_id),
lvl6 as
(select x.parent_id, x.child_id
from tbl x
left join lvl5
on x.parent_id = lvl5.child_id),
lvl7 as
(select x.parent_id, x.child_id
from tbl x
left join lvl6
on x.parent_id = lvl6.child_id),
lvl8 as
(select x.parent_id, x.child_id
from tbl x
left join lvl7
on x.parent_id = lvl7.child_id)
select parent_id,
case when lag(child2,1) over (partition by parent_id order by parent_id) = child2 then null else child2 end as child2,
case when lag(child3,1) over (partition by parent_id order by parent_id) = child3 then null else child3 end as child3,
case when lag(child4,1) over (partition by parent_id order by parent_id) = child4 then null else child4 end as child4,
case when lag(child5,1) over (partition by parent_id order by parent_id) = child5 then null else child5 end as child5,
case when lag(child6,1) over (partition by parent_id order by parent_id) = child6 then null else child6 end as child6,
case when lag(child7,1) over (partition by parent_id order by parent_id) = child7 then null else child7 end as child7,
case when lag(child8,1) over (partition by parent_id order by parent_id) = child8 then null else child8 end as child8
from(
select distinct
lvl1.parent_id,
lvl2.parent_id as child2,
nvl(lvl3.parent_id,lvl2.child_id) as child3,
nvl(lvl4.parent_id,lvl3.child_id) as child4,
nvl(lvl5.parent_id,lvl4.child_id) as child5,
nvl(lvl6.parent_id,lvl5.child_id) as child6,
nvl(lvl7.parent_id,lvl6.child_id) as child7,
nvl(lvl8.parent_id,lvl7.child_id) as child8
from lvl1
left join lvl2
on lvl1.child_id = lvl2.parent_id
left join lvl3
on lvl2.child_id = lvl3.parent_id
left join lvl4
on lvl3.child_id = lvl4.parent_id
left join lvl5
on lvl4.child_id = lvl5.parent_id
left join lvl6
on lvl5.child_id = lvl6.parent_id
left join lvl7
on lvl6.child_id = lvl7.parent_id
left join lvl8
on lvl7.child_id = lvl8.parent_id
order by parent_id)
| PARENT_ID | CHILD2 | CHILD3 | CHILD4 | CHILD5 | CHILD6 | CHILD7 | CHILD8 |
|-----------|--------|--------|--------|--------|--------|--------|--------|
| 15 | 12 | 5 | 23 | (null) | (null) | (null) | (null) |
| 17 | 12 | 5 | 23 | (null) | (null) | (null) | (null) |
| 21 | 20 | 4 | 23 | (null) | (null) | (null) | (null) |
| 21 | (null) | (null) | 39 | (null) | (null) | (null) | (null) |
| 30 | (null) | (null) | (null) | (null) | (null) | (null) | (null) |