2014-11-03 56 views
0

我嘗試編寫一個SQL查詢(使用完全外部聯接),該查詢從三個彼此相關的表通過n:m關係創建完整的結果集。從Oracle數據庫中的複雜n:m關係獲取結果集

最初的情況是一個具有三個實體的歸一化數據模型:人,神器和位置。每個實體通過由交集表表示的n:m關係與每個其他實體相關。

person { person_id, ... } 
artifact { artifact_id, ... } 
location { location_id, ... } 

rel_person_artifact { person_id, artifact_id, role_id } 
rel_person_location { person_id, location_id, role_id } 
rel_artifact_location { artifact_id, location_id, role_id } 

我的目標是創建一個包含所有的人,文物和位置的所有三個表的結果集。

爲了解決這個問題,我嘗試了以下聲明:

select 
    * 
from 
    person per 
    full outer join rel_person_artifact rpa on per.person_id = rpa.person_id 
    full outer join artifact art on art.artifact_id = rpa.artifact_id 
    full outer join rel_artifact_location ral on ral.artifact_id = art.artifact_id 
    full outer join location loc on loc.location_id = ral.location_id 
    full outer join rel_person_location rpl on rpl.person_id = per.person_id; 

該查詢syntatically正確的,但回報是內容撥錯,因爲其他後加入處理一個表。在一天結束時,並不是每個關係都在結果集中表示。

有什麼辦法可以將上述表結合起來以獲得完整和正確的結果集?

編輯。下面是一些樣本記錄(I粘到交叉點表):

rel_person_artifact ('Peter', 'car 1', 'owner'), ('Alex', 'car 1', 'driver') 
rel_person_location ('Peter', 'location 1', 'home'), ('Paul', 'location 2', 'place of work') 
rel_artifact_location ('car 1', 'location 1', 'parking') 

。當然,數據可以比本實施例中更復雜。正如下面的評論中提到的那樣,也可能存在循環關係。

我不確定結果集應該是什麼樣子,我甚至不確定天氣這個組合是可能的嗎?

非常感謝!

問候

+0

不要使用'OUTER JOIN'來代替使用'INNER JOIN'。我不知道,但它可能會起作用。 – 2014-11-03 09:50:40

+2

提供一些示例數據和一個示例結果集可能是一個好主意。 – Fred 2014-11-03 09:52:36

+0

考慮交叉表中的以下3行:rel_person_artifact('Jim','Pencil','x'); rel_person_location( '吉姆', '倫敦', 'Y'); rel_artifact_location( '鉛筆', '巴黎', 'Z'); - 你的查詢的結果是什麼? – 2014-11-03 10:04:09

回答

0

我終於通過使用LEFT JOINUNION組合解決了這個問題。您可以分解屬於某個角度的關係。這意味着您首先通過LEFT JOIN建立所需的觀點,然後通過UNION合併這些觀點。

因此,給出的例子可以解決如下:

-- person perspective 
select 
    per.person_id person_id, 
    art.artifact_id artifact_id, 
    loc.location_id location_id, 
    rpa.role_id person_artifact_role_id, 
    rpl.role_id person_location_role_id, 
    null artifact_location_role_id -- This attribute cannot be filled in this perspective, so it has to be null to fit the common structure of both perspectives. 
from 
    person per 
    left join rel_person_artifact rpa on rpa.person_id = per.person_id 
    left join artifact art on art.artifact_id = rpa.artifact_id 
    left join rel_person_location rpl on rpl.person_id = per.person_id 
    left join location loc on loc.location_id = rpl.location_id 

union 

-- location perspective 
select 
    per.person_id person_id, 
    art.artifact_id artifact_id, 
    loc.location_id location_id, 
    null person_artifact_role_id, -- see above 
    rpl.role_id person_location_role_id, 
    ral.role_id artifact_location_role_id 
from 
    location loc 
    left join rel_artifact_location ral on ral.location_id = loc.location_id 
    left join artifact art on art.artifact_id = ral.artifact_id 
    left join rel_person_location rpl on rpl.location_id = loc.location_id 
    left join person per on per.person_id = rpl.person_id 

-- ... 

即與UNION連接,以滿足共同的結構,所以你必須添加一個新的時來調整各個角度各個角度。

感謝您的回覆,希望這將有助於任何人面臨類似的問題。