从Oracle数据库中的复杂n:m关系中获取结果集

时间:2014-11-03 09:46:31

标签: sql oracle11g full-outer-join

我尝试编写一个SQL查询(使用完全外部联接),该查询通过n:m-relationships从三个彼此相关的表创建完整的结果集。

最初的情况是具有三个实体的标准化数据模型:人,工件和位置。每个实体通过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;

此查询在语法上是正确的,但返回了worng内容,因为连接处理一个表到另一个表。在一天结束时,并不是每个关系都在结果集中表示。

有没有办法合并上面的表格以获得完整正确的结果集?

编辑。以下是一些示例记录(我坚持交叉表):

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

当然,数据可能比这个例子复杂得多。如下面的评论所述,也可能存在循环关系。

我不确定结果集应该是什么样子,我甚至不确定天气这种组合是否可行?

非常感谢!

此致

1 个答案:

答案 0 :(得分: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相关联的每个视角都适合公共结构,因此在添加新视角时,您必须调整每个视角。

感谢您的回复,希望这有助于任何遇到类似问题的人。