我有一个表TABA(PK:NAME)以这种方式存储NAME,NAME_TYPE,SOURCE:
NAME NAME_TYPE SOURCE
---- --------- ------
Name1 Category S1
Name2 Category S2
Name3 Datamart
Name4 Category S1
Name5 Datamart
Name6 Datamart
Name7 Category S3
上面的注意:只有当NAME_TYPE = Category时,数据才会出现。
我有另一个表TABA_PARENT,它以这种方式基于name_type存储NAME,PARENT_NAME与NAME列之间的关系。 Datamart与Category的关系是一对多的。
NAME PARENT_NAME
----- -----------
Name3 Name1
Name3 Name2
Name3 Name4
Name3 Name5
Name5 Name1
Name5 Name6
Name6 Name7
我的要求是获取TABA的SOURCE,其中NAME_TYPE = Datamart(目前,它在TABA中不存在)
预期产出:
SOURCE column for Name3
-----------------------
S1,S2,S3
诀窍是递归推导出Name3的SOURCE,直到它映射到TABA_PARENT中的类别。
在上面的例子中:
Name3映射到PARENT_NAME Name1,Name2,Name4,Name5。 其中3个(name1,Name2,Name4)属于name_type = Category,因此在TABA中可以使用不同的源 - S1,S2 第四个PARENT_NAME Name5是一个name_type Datamart(源信息不可用),需要进一步扩展,直到达到name_type = Category。
我们拥有Name5映射到PARENT_NAME Name1,Name6的信息。 Name1是一个类别,因此可以推断出来源。 Name6又是Datamart。
但是,Name6最终映射到Name7,这是一个类别,因此源可用 - S3
如上所示,所有映射都必须以递归方式解析,直到达到name_type类别以识别不同的源。
Expected Result: S1,S2,S3
我正在尝试使用listagg或类似的东西(小的pl / sql代码也可以,但是如果可能的话更喜欢sinlge选择) 我很难递归地做到这一点。 任何帮助将不胜感激。
答案 0 :(得分:2)
正如评论中所述,这可以通过listagg()
的组合来完成,connect by
可以从Oracle 11.2开始和a number of other string aggregation techniques available获得。如果你没有使用11.2那么就有SQL Fiddle。
select listagg(source, ',' ) within group ( order by source )
from ( select distinct source
from taba a
join ( select parent_name
from taba_parent
start with name = 'Name3'
connect by prior parent_name = name
) b
on a.name = b.parent_name
)
distinct
子查询仅在那里,因为您有多个相同的源。这将返回S1,S2,S3
。
为了获得不同名称的相同名称,您可以更改START WITH子句;例如,将其更改为start with name = 'Name5'
会返回S1,S3
。
数据集市没有源这一事实并不重要,因为您只在taba_parent
表上使用分层查询,只有在您拥有信息时才加入taba
表需要。
答案 1 :(得分:1)
感谢有人试图这样做。 我尝试使用“connect by”和listagg的组合,并获得了预期的结果。
select listagg(source,',') within group (order by source) final_source from (
select
distinct
b.source source--,
from taba_parent a, taba b
where b.name = a.parent_name
and b.name_type = 'Category'
connect by prior a.parent_name = a.name
start with a.name = 'Name3'
);
答案 2 :(得分:0)
您需要一个分层查询(连接)才能获得“终极父级”,然后您需要使用listagg将这些项连接在一起。我只有Oracle 10g,所以我没有listagg。这是分层位:
select distinct source from
(
select taba_parent.name, taba_parent.parent_name, taba.source
from
taba_parent
inner join taba on taba_parent.parent_name = taba.name
)
where name in (select name from taba where name_type = 'Datamart')
connect by name = parent_name
start with source is not null
这给出了:
SOURCE
S3
S2
S1
你可以使用listagg来获得S3,S2,S1