2017-04-13 55 views
0

這是我的第一個問題,因此對任何禮儀錯誤表示歉意!如何使用SQL Oracle數據庫返回特定的父/子結果

我有三個相關的表...

ID - 該表列出了所有記錄
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 

這裏是我的查詢的一個簡單的例子:

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') 

我想要的是返回所有記錄中,其中(父)PROPER_ID或者是在第1列然後1,2,3,4,第2欄,我想回到孩子正確的記錄ID (如果該記錄在「詳細信息」表中有'A')。對於第3列,我想要做與第2列相同的操作,但在DETAILS表中有一個帶有'B'的子記錄。

有4分可能的情況,我可以看到:
1.有0子記錄與詳細信息表中的「A」或「B」 - 在這種情況下,我想返回一行只有家長Proper_ID並在隨後的2欄中空白。
2.在細節表中有一個或多個帶'A'的子記錄 - 在這種情況下,我想返回與子記錄一樣多的行。
3.如上所述,但在細節表中只有'B'。
4.有'A'和'B'子記錄 - 在這種情況下,如果每個記錄中有一個,我想在同一行上重新顯示所有數據。

電流輸出

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

謝謝@ alex-poole - 我已經添加了這些 - 希望不會太複雜 – AlexJ

+0

ID.PROPER_ID與ID.KEY或其他東西一樣嗎?您發佈的查詢不會始終使用別名,這有點令人困惑。父母/子女關係只有一級 - 沒有孫子女? (不知道爲什麼你有一個單獨的父/子表,而不是ID中的父列) –

回答

0

我認爲你可以做你想做一個支點是什麼(11g或更高版本;手動版有可能在更早的版本),這樣的:

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。如果父母有超過A的記錄,他們將被配對,這可能是也可能不是你想要的,但目前還不清楚這是否會發生。

與樣品數據,熱膨脹係數:

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

相關問題