2017-04-13 5 views
0

で特定の親/子結果を返す方法これは私の最初の質問ですので、エチケットのエラーのためにお詫び申し上げます!私は3つの関連するテーブルを持っているSQL Oracleデータベース

...

IDは - これは自分の子レコード
DETAILSと親レコードをリンク - - このテーブルには、すべてのレコード
PARENT_CHILD_RELATIONSHIPための目に見えるIDが提供するすべてのレコード

の詳細を提供します

サンプル・データここで

Table ID     PARENT_CHILD_RELATIONSHIP DETAILS 
Columns KEY|PROPER_ID  PARENT_KEY|CHILD_KEY  KEY|FIELD 
     1|P1    1|NULL      5|A 
     2|P2    2|5      5|C 
     3|P3    2|6      6|A 
     4|P4    3|7      6|D 
     5|C1    4|8      7|B 
     6|C2    4|9      7|C 
     7|C3           8|A 
     8|C4           8|C 
     9|C5           9|B 
                 9|C 

は私のクエリの単純化した例です。

(親)PROPER_IDが列2に、次いで、カラム1のいずれかである1,2,3,4-どこのすべてのレコードを返すことです、私は子レコードの適切なIDを返すようにしたい私は何をしたい
SELECT DISTINCT I.PROPER_ID, CHILD_ID_A.PROPER_ID, CHILD_ID_B.PROPER_ID 

FROM ID I     

LEFT OUTER JOIN PARENT_CHILD_RELATIONSHIP PCR_A ON PCR_A.PARENT_KEY = I.KEY 
LEFT OUTER JOIN DETAILS D_A ON D_A.KEY = PCR_A.CHILD_KEY 
AND D_A.FIELD = ('A')     
LEFT OUTER JOIN ID CHILD_ID_A ON CHILD_ID_A.KEY = DETAILS_A.KEY 

LEFT OUTER JOIN PARENT_CHILD_RELATIONSHIP PCR_B ON PCR_B.PARENT_KEY = I.KEY 
LEFT OUTER JOIN DETAILS D_B ON D_B.KEY = PCR_B.CHILD_KEY 
AND D_B.FIELD = ('B')     
LEFT OUTER JOIN ID CHILD_ID_B ON CHILD_ID_B.KEY = DETAILS_B.KEY 

WHERE I.PROPER_ID IN('1', '2', '3', '4') 

そのレコードの詳細テーブルに「A」が含まれている場合列3については、列2と同じようにしたいが、DETAILS表に「B」を持つ子レコードがある場合。

私が見ることができる4つの可能なシナリオがあります。
1.Thereは、詳細テーブル「A」または「B」と0子レコードです - このケースでは、私はちょうど親Proper_IDを持つ単一の行を返すようにしたいです次の2つの列に空白があります。
2.詳細テーブルに「A」を含む子レコードが1つ以上あります。この場合、子レコードがある行数だけ戻したいと考えています。
3.上記と同じですが、詳細テーブルに「B」のみがあります。
4.「A」と「B」の両方の子レコードがあります。この場合、それぞれが1つの場合は、同じ行のすべてのデータを再実行します。

電流出力

I.PROPER_ID | CHILD_ID_A.PROPER_ID | CHILD_ID_B.PROPER_ID 
P1   | NULL     | NULL 
P2   | C1     | NULL 
P2   | C2     | NULL 
P2   | NULL     | NULL 
P3   | NULL     | C3 
P3   | NULL     | NULL 
P4   | C4     | C5 
P4   | C4     | NULL 
P4   | NULL     | C5  
P4   | NULL     | NULL 

出力は私がしたい:

I.PROPER_ID | CHILD_ID_A.PROPER_ID | CHILD_ID_B.PROPER_ID 
P1   | NULL     | NULL 
P2   | C1     | NULL 
P2   | C2     | NULL 
P3   | NULL     | C3 
P4   | C4     | C5 

がこのさえ可能ですか?私は多くの異なるバリエーションを試してみて、他の例を探してみましたが、解決策を見つけられませんでした。

ご協力いただければ幸いです!

+1

あなたの質問にいくつかのサンプルデータと期待される出力を含めると便利です。現在のクエリで問題がどのようなものであるかを示します。 –

+0

ありがとう@アレックスポール - 私はそれらを追加しました - うまくいけばあまり複雑ではない – AlexJ

+0

ID.PROPER_IDはID.KEYと同じですか?あなたが投稿したクエリは、エイリアスを一貫して使用していません。少し混乱します。親子関係のレベルは1つしかない - 孫はいない? (IDの親カラムではなく、親/子テーブルの別のテーブルがある理由はわかりません) –

答えて

0

私はあなたがピボットとあなたがやりたいことができると思います;のようなもの、(11グラム以上の手動バージョンは、以前のリリースで可能です):

select * from (
    select p.proper_id as parent_id, c.proper_id as child_id, d.field, 
    row_number() over (partition by p.key, d.field order by c.key) as rn 
    from id p 
    join parent_child_relationship pcr on pcr.parent_key = p.key 
    left join id c on c.key = pcr.child_key 
    left join details d on d.key = c.key and d.field in ('A', 'B') 
    where p.proper_id in ('P1', 'P2', 'P3', 'P4') 
) 
pivot (max(child_id) as child for (field) in ('A' as a, 'B' as b)) 

内側のクエリでrow_number()が、それは続けることができますP2のための2つの別々の行。親がA Bレコード以上のレコードを持っている場合、それらはペアになります。これはあなたが望むかもしれないし、そうでないかもしれませんが、どうにか起こることがあるかどうかは不明です。CTEは、あなたのサンプルデータで

with ID (KEY, PROPER_ID) as (
    select 1, 'P1' from dual 
    union all select 2, 'P2' from dual 
    union all select 3, 'P3' from dual 
    union all select 4, 'P4' from dual 
    union all select 5, 'C1' from dual 
    union all select 6, 'C2' from dual 
    union all select 7, 'C3' from dual 
    union all select 8, 'C4' from dual 
    union all select 9, 'C5' from dual 
), PARENT_CHILD_RELATIONSHIP (PARENT_KEY, CHILD_KEY) as (
    select 1, null from dual 
    union all select 2, 5 from dual 
    union all select 2, 6 from dual 
    union all select 3, 7 from dual 
    union all select 4, 8 from dual 
    union all select 4, 9 from dual 
), DETAILS (KEY, FIELD) as (
    select 5, 'A' from dual 
    union all select 6, 'A' from dual 
    union all select 7, 'B' from dual 
    union all select 8, 'A' from dual 
    union all select 9, 'B' from dual 
) 
select parent_id, a_child as child_a_id, b_child as child_b_id 
from (
    select p.proper_id as parent_id, c.proper_id as child_id, d.field, 
    row_number() over (partition by p.key, d.field order by c.key) as rn 
    from id p 
    join parent_child_relationship pcr on pcr.parent_key = p.key 
    left join id c on c.key = pcr.child_key 
    left join details d on d.key = c.key and d.field in ('A', 'B') 
    where p.proper_id in ('P1', 'P2', 'P3', 'P4') 
) 
pivot (max(child_id) as child for (field) in ('A' as a, 'B' as b)) 
order by 1, 2, 3; 

生成:

PARENT_ID CHILD_A_ID CHILD_B_ID 
--------- ---------- ---------- 
P1        
P2  C1     
P2  C2     
P3     C3   
P4  C4   C5   

を、あなたがより明示的に同じことを行うことができますpivotサポートしていない以前のリリースにしている場合:

select parent_id, 
    max(case when field = 'A' then child_id end) as child_a_id, 
    max(case when field = 'B' then child_id end) as child_b_id 
from (
    select p.proper_id as parent_id, c.proper_id as child_id, d.field, 
    row_number() over (partition by p.key, d.field order by c.key) as rn 
    from id p 
    join parent_child_relationship pcr on pcr.parent_key = p.key 
    left join id c on c.key = pcr.child_key 
    left join details d on d.key = c.key and d.field in ('A', 'B') 
    where p.proper_id in ('P1', 'P2', 'P3', 'P4') 
) 
group by parent_id, rn 
order by 1, 2, 3; 
+0

私は9iを実行している場合は、あなたの答えのためにあまりにもありがとう、ピボットのマニュアルバージョンに提供できるアドバイスはありますか? – AlexJ

+0

@AlexJ - 最後に手動バージョンを追加しました。とにかく 'pivot'構文は同じことをフードの下で行います。 –

+0

私はこれを回答としてマークし、ご協力いただきありがとうございます。あなたがチャンスを持っていれば、Whereステートメント(WHERE I.PROPER_ID IN( '1'、 '2'、 '3'、 '4'))を追加するように編集できますか? – AlexJ