2011-08-05 20 views
11

私はデータベースに各識別子の次の2つの情報を持っています。彼らを支配する会社、小さな支配権を持っている会社。SQLマルチコンディションCTE再帰

線に沿って何か、2つのテーブル(いくつかのユニークな識別子を無視して):

団体

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

関係ORGID - > org_immediate_parent_orgid意味会社は、親を持っています。ポル私は唯一org_immediate_parent_orgidその関連 - > affiliated_orgid当社は視覚的な表現があるべきアフィリエイト

を持っている - >は、企業の親会社が子会社として

org_affiliations

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

ORGIDがあり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
  • サブ - >サブ

私はSub - > Sub(子会社の子会社)、リレーション(2 - > 1、リレーション1 - > 3)、Aff - > Aff、リレーションシップ関係2→5)。また、それは私に2つの別のクエリが必要です。

1つの再帰的クエリですべての可能な関係をどのように取り出すことができますか?

私は識別子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つのクエリ。私はすべての子会社と関連会社とすべての潜在的なsubs \ affsの組み合わせを見つける会社からどこに単一のクエリが欲しい。最終的な予想結果は、画像の表記に従うだけです。

編集:クレイグ氏のコメント通り、私は出力を修正しました。

Edit2:良い助けに続いて、CraigとBob Jarvisは私に問題を抱え続けました。収集子会社の

、次のコードはflawlessyの作品、と私は希望として出力されます。

AFFのための同じ
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 

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 

が、 "労働組合のすべてを" 持ってカント?私が行ったSQLの開発者で

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 

と労働組合のすべて 『どれworkarround「を追加するだけで、400Kまで7からそれぞれのジャンプからの計画とコストを説明する』チェック?CTE内部の問題は、UNION ALLで、ですか?私はCOMP-サブサブAFF持っている、またはそれは、会社のすべての子会社または全ての関連会社

+2

+1せん断の美しさ。私は、読んで理解し、返信するのはD – Bohemian

+1

を聞いていませんでした! – blueomega

+1

ITSは長すぎる:しかし、あまりにも長い...何とか説明しなければならなかった:) – 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

これをコメントから実際の回答に移動し、必要と思われるものを提供します。

いくつかのものはマイナーなものです。私はあなたの最初の接続のラベルが後方への出力によって接続されていると信じています。また、最終出力で最後の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を使用しています。

また、何らかの理由で、Oracleは最初のループに自己参照であるため、他のループとは異なるレベルを与えます。私はこれが問題であれば、この場合のカスタムロジックを入れることができると仮定しています。

+0

こんにちはクレイグ、ラベル交換は問題ありません、このデータを食べるシステムは気にしません。アップス4は5の子会社でなければなりません。全体的に、素晴らしい仕事、就寝時間を過ぎましたが、後でそれをテストしてより多くのフィードバックを提供します。すべての変更は今すぐ簡単にする必要があります:) – blueomega

+0

私はまだ上に説明した問題に遭遇しているようです。私はOracleは、特定のだと思う「ナルPARENT_ID」私はそれを正しく理解すれば、私は – 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; 

これで、興味のあるすべての組織を繰り返し簡単に見つけることができます。

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列を削除できますが、あなたは削除するか、どこの部分を変更し、related_recursiveから*を選択したい場合には、 便利かつ必要です。

CTEはメインクエリの前に完全に評価されるので、メインクエリで最終的なフィルタリングを行う前に多くのページを取得する可能性があることを覚えておいてください。

+0

AFFこれ以上に企業の出力IDが必要いけない、私はあなたがして接続を使用し表示されませんでした、とクエリの一部? oracleがまだそれをサポートしていなければ、これを標準の "再帰的な"から変換することは問題ではありません。 –