2011-08-05 180 views
11

余数据库I具有的每个标识信息的2个以下。控制他们的公司,以及他们有一点控制权的公司。SQL多条件CTE递归

沿东西线,2台(忽略了一些独特的标识符):

组织

orgid | org_immediate_parent_orgid 
1  | 2 
2  | 2 
3  | 1 
5  | 4 

的关系ORGID - > org_immediate_parent_orgid意味着公司拥有母公司。 POR我及其相关仅org_immediate_parent_orgid - > ORGID公司的母公司拥有作为辅助

org_affiliations

orgid | affiliated_orgid 
2  | 3 
2  | 5 
4  | 1 
1  | 5 

ORGID - > affiliated_orgid是公司拥有子公司

的可视化表示应例如:

Database representation

在从组织红色的关系,蓝色的关系org_affiliations

如果想要得到2(2或子公司的儿子)拥有的所有公司中有他们的一些部分:

select m.org_immediate_parent_orgid 
,m.orgid 
from oa.organizations m 
where m.org_immediate_parent_orgid is not null 
start with m.orgid in (Identifiers) 
connect by nocycle prior m.orgid=m.org_immediate_parent_orgid 

回报

org_immediate_parent_orgid| orgid 
1       | 2 
2       | 2 
3       | 1 

如果想要获得所有的公司分别为2 (或2下属子)中有他们一些部分:

select aff.orgid,aff.affiliated_orgid 
from oa.org_affiliations aff 
where aff.affiliated_orgid is not null 
start with aff.orgid in(Identifiers) 
connect by nocycle prior aff.affiliated_orgid =aff.orgid 

回报

orgid | affiliated_orgid 
2  | 3 
2  | 5 

因此,所有可能的关系:

  • AFF - > AFF
  • AFF - >子
  • 子 - > AFF
  • 子 - >子

我只能找到子 - >子(子公司子公司),关系(2 - > 1和关系1 - > 3)和AFF - > AFF,关系(2 - >图3和关系2 - > 5)。另外它需要我2个单独的查询。

我怎么能拉一个单一的递归查询所有可能的关系?

如果我通过标识2应该尽可能以下返回:

Relation | Loop| orgid | children 
Sub  | 1 | 2  |2 
Sub  | 1 | 2  |1 
Aff  | 1 | 2  |3 
Aff  | 1 | 2  |5 
Sub  | 2 | 1  |3 
Aff  | 2 | 1  |5 

在每个循环中会检查潜艇和附属公司的每个标识符。重复为新的孩子。

对如何处理它的主意?

TL:DR: 2表(子公司\附属公司),2查询。希望从一家公司的单个查询中找到所有子公司和附属公司以及所有可能的子\ affs组合。最终预期结果显示,只需按照图片表示即可。

编辑:由Craig评论,我修正了输出。

编辑2:以下的好帮手克雷格和鲍勃贾维斯给我继续遇到问题。

收集子公司,下面的代码工作flawlessy,输出是因为我想:

with 
relations as 
(
select orgid as children,org_immediate_parent_orgid as orgid,'Sub' as relation 
from oa.organizations 
) 
select distinct relation, level, orgid, children 
from relations 
where children is not null 
start with orgid in (identifier) 
connect by 
nocycle prior children = orgid 
order by 2,3,4 

同为AFF:

with 
relations as 
(
select affiliated_orgid as children, orgid as orgid,'Aff' as relation 
from oa.org_affiliations  
) 
select distinct relation, level, orgid, children 
from relations 
where children is not null 
start with orgid in (identifier) 
connect by 
nocycle prior children = orgid 
order by 2,3,4 

,但不能有 “UNION ALL”?

with 
relations as 
(
select orgid as children,org_immediate_parent_orgid as orgid,'Sub' as relation 
from oa.organizations 

UNION ALL 

select affiliated_orgid as children, orgid as orgid,'Aff' as relation 
from oa.org_affiliations  
) 
select distinct relation, level, orgid, children 
from relations 
where children is not null 
start with orgid in (identifier) 
connect by 
nocycle prior children = orgid 
order by 2,3,4 

在SQL开发人员,我就去检查“从7每一跳到400K解释计划和成本,只需通过添加‘UNION ALL’。任何workarround?是CTE内部的问题,在UNION ALL?

在那里我有COMP-分次AFF,或者发现公司的所有子公司或附属机构为

+2

+1剪切美。然而,太长...没有听:) – Bohemian

+1

不得不解释:D – blueomega

+1

它太长,我阅读,理解和回复! – Kangkan

回答

1

这里的情况鲍勃·贾维斯的解决方案不会工作是在它开始:

select 'SUB -> SUB' AS TYPE, 
     m.orgid AS ORGID, 
     m.org_immediate_parent_orgid AS PARENT_OR_AFF 
    from organizations m 
    where m.org_immediate_parent_orgid is not NULL 
    start with m.orgid in (2) 
    connect by nocycle prior m.orgid = m.org_immediate_parent_orgid 
UNION ALL 
select 'AFF -> AFF' AS TYPE, 
     aff.orgid AS ORGID, 
     aff.affiliated_orgid AS PARENT_OR_AFF 
    from org_affiliations aff 
    where aff.affiliated_orgid is not NULL 
    start with aff.orgid IN (2) 
    connect by nocycle prior aff.affiliated_orgid = aff.orgid; 

如果你添加子查询来获得剩余的关系,你应该很好去。

分享和享受。

2

从一个实际的答案评论移动这一点并提供什么,我相信你所需要的。

一对夫妇的东西..一个是次要的。我相信你有你的第一个的标签由返回输出连接倒退。另外,我不明白你如何获得最终输出中的最后两行。 4是5的父母,不是孩子,为什么它出现?如果它不在那里,那么最后一条线就不会那么好。

如果我正确地读它,你可以使用类似:

with 
relations as 
(
    select 
     orgid, 
     org_immediate_parent_orgid parent_id, 
     'Sub' relation 
    from 
     organizations 
    union all 
    select 
     orgid, 
     null parent_id, 
     'Aff' relation 
    from 
     org_affiliations 
    where 
     orgid not in (
      select affiliated_orgid 
      from org_affiliations 
     ) 
    union all 
    select 
     affiliated_orgid orgid, 
     orgid parent_id, 
     'Aff' relation 
    from 
     org_affiliations 
) 
select distinct relation, level, parent_id, orgid 
from relations 
where parent_id is not null 
start with orgid = 2 
connect by 
    nocycle prior orgid = parent_id 
order by 2,3,4 

这给下面的输出:

RELATION|LEVEL|PARENT_ID|ORGID 
Sub  |1 |2  |2 
Sub  |2 |2  |1 
Aff  |2 |2  |3 
Aff  |2 |2  |5 
Sub  |3 |1  |3 
Aff  |3 |1  |5 

最重要的事情是,2台分别建立了相对的彼此(组织与父母有联系,联系与孩子有联系)。所以我在WITH子句中将它们转换为相同的格式,然后在组合集上使用connect by。

此外,由于某种原因,甲骨文给人的第一循环不同的级别比别人,因为它是一个自我引用。我假设如果这是一个问题,你可以在这个案例中加入一些自定义逻辑。

+0

嗨克雷格,标签交换没有问题,吃这个数据的系统并不在意。 Ups 4应该是5的子公司,而不是相反,优秀的捕获。总而言之,出色的工作,超过我的就寝时间,但后来不好测试,并提供更多的反馈意见。现在任何改变都应该很容易:) – blueomega

+0

似乎我仍然遇到问题,上面解释过。该查询的部分与“null parent_id”,如果我理解正确,我不需要公司的输出ID没有更多的aff – blueomega

0

未经检验。创建一个视图,以便首先简化从2个表中提取数据。

create view related(orgid, relatedid) as 
    select orgid, org_immediate_parent_orgid as relatedid from organizations 
    union distinct 
    select orgid, affiliated_orgid as relatedid from affiliated; 

现在我们可以使用它轻松地迭代查找所有有趣的orgids。

with recursive related_recursive(orgid, relatedid) as (
    select orgid, relatedid from related where relatedid = 2 
    union 
    select r.origid, rr.relatedid from related_recursive rr, related r 
     where rr.orig = r.relatedid 
) 
select orgid from related_recursive; 

你甚至可以删除的related_recursive的relatedid列在这种情况下,但如果你想删除或更改其中一部分,SELECT * FROM related_recursive它是有用的 和必要的。请记住,CTE在主查询之前会被完全评估,因此在主查询中最终过滤之前,这可能会拉动很多页面 。

+0

我没有看到你使用连接,我认为是特定于甲骨文?如果oracle不支持它,将它从标准的“递归”转换成应该没有问题。 –