2

我有一个表 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 列之间的关系。Datamart 与类别的关系是一对多的。

  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 又是一个数据集市。

但是,Name6 最终映射到作为 Category 的 Name7,因此源可用——S3

如上所示,所有映射都必须递归解析,直到它们到达 name_type 类别以识别不同的源。

Expected Result: S1,S2,S3 

我正在尝试是否可以使用 listagg 或类似的东西来完成(小的 pl/sql 代码也可以,但如果可能的话更喜欢单选)我很难递归地做到这一点。任何帮助将非常感激。

4

3 回答 3

3

正如评论中所指出的,这可以通过结合listagg()使用 (从 Oracle 11.2 开始提供)和connect by. 如果您不使用 11.2,那么还有许多其他可用的字符串聚合技术

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来演示。

于 2012-09-04T19:16:04.323 回答
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'        
);
于 2012-09-04T22:02:35.073 回答
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

于 2012-09-04T19:13:08.847 回答