我有一个表 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、PARENT_NAME 以及基于 name_type 的 NAME 列之间的关系。 数据集市与类别的关系是一对多。
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 数据集市(源信息不可用),需要进一步扩展,直到达到 name_type = Category。
我们有信息 Name5 映射到 PARENT_NAME Name1、Name6。 Name1 是一个类别,因此可以推断出来源。 Name6 再次成为数据集市。
但是,Name6 最终映射到 Name7,这是一个类别,因此源可用 - S3
如上所示,所有映射都必须递归解析,直到到达 name_type 类别才能识别不同的源。
Expected Result: S1,S2,S3
我正在尝试是否可以使用listagg或类似的东西来完成此操作(小的pl/sql代码也可以,但如果可能的话更喜欢sinlge select) 我很难递归地执行此操作。 任何帮助将不胜感激。
最佳答案
正如评论中所述,这可以通过 listagg()
的组合来完成,从 Oracle 11.2 及 connect by
开始提供。如果您不使用 11.2,则有 a number of other string aggregation techniques available .
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
表当您获得所需的信息时。
这里有一点SQL Fiddle演示。
关于sql - 递归oracle sql来识别一个值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12268334/