我尝试编写一个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' )
当然,数据可能比这个例子复杂得多。如下面的评论所述,也可能存在循环关系。
我不确定结果集应该是什么样子,我甚至不确定天气这种组合是否可行?
非常感谢!
此致
答案 0 :(得分:0)
我最终使用LEFT JOIN
和UNION
的组合解决了这个问题。您可以解散属于某个角度的关系。这意味着您首先通过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
相关联的每个视角都适合公共结构,因此在添加新视角时,您必须调整每个视角。
感谢您的回复,希望这有助于任何遇到类似问题的人。