我有一个表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
我的要求是获取NAME_TYPE = Datamart的TABA的源(当前,TABA中不存在)
预期产量:
SOURCE COLUMN FOR Name3
-----------------------
S1,S2,S3
诀窍是递归推导Name3的SOURCE,直到它映射到TABA_PARENT中的Category。
在上面的示例中:
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最终被映射到属于Category的Name7,因此源可用-S3
如上所示,必须递归解析所有映射,直到它们到达name_type Category以标识不同的源。
Expected RESULT: S1,S2,S3
我正在尝试是否可以使用listagg或类似的东西来完成此操作(小的pl / sql代码也可以,但是如果可能的话,请选择单选)
我很难递归地执行此操作。
任何帮助将非常感激。
我无法回答自己的问题。 因此,我在评论部分中回答。
感谢任何尝试此操作的人。 我尝试使用" connect by"和listagg的组合,并达到了预期的效果。 在组(按源排序)中选择listagg(source ,,),按final_source从(选择不同的b.source源-,从taba_parent a,taba b中选择,其中b.name = a.parent_name和b.name_type = Category按先前a连接 .parent_name = a.name以a.name = Name3开头);
如果您不愿意接受其他第一章的答案之一,则将其发布为答案。
我试图这样做,但是该网站不允许我接受48小时的自己的答案。 之后,我将接受自己的回答。
如注释中所述,可以使用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演示。
谢谢大家,我看到提供的解决方案与我提出的解决方案相同,并且所有这些工作都可以解决。
感谢任何尝试此操作的人。
我尝试使用" 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'
);
您需要一个层次查询(connect by)来获得"最终父母",然后您需要使用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
谢谢大家,我看到提供的解决方案与我在您的回复和所有这些工作之前提出的解决方案相同。