存在多对多的关系

时间:2017-06-12 15:06:15

标签: sql amazon-redshift

我正在使用Amazon Redshift,无法正确查询。假设我有很多项目,每个项目都需要一项或多项技能。所以项目和技能之间存在多对多的关系。用户创建项目,因此每个项目都有一个创建者。

对于每个项目,我希望由共享至少一项技能的同一创建者获得所有其他项目。所以我想写这样的东西:

SELECT p1.project_id, p2.project_id
FROM projects p1 
JOIN projects p2 on p1.creator = p2.creator
WHERE EXISTS (SELECT 0
              from skills sk1, skills sk2 
              where sk1.project_id = p1.project_id 
                and sk2.project_id = p2.project_id 
                and sk1.skill = sk2.skill)

问题是这是真的(给出disk full错误)。

以下作品,但也很慢(需要半个小时左右):

SELECT distinct p1.project_id, p2.project_id
FROM projects p1
  JOIN projects p2 on p1.creator = p2.creator
  join skills sk1 on sk1.project_id = p1.project_id
  join skills sk2 on sk2.project_id = p2.project_id
WHERE sk1.skill = sk2.skill

这个问题是,如果我想在第二个项目上聚合一些属性,我必须使用它作为子查询。

有更好的方法吗?我认为第一个查询会更快,因为它在选择单个项目时停止。

1 个答案:

答案 0 :(得分:1)

您的查询的一个简单问题是您允许项目加入自己。这意味着将返回每个项目。

通过确保加入的两个项目不相同来修复它:

JOIN projects p2 on 
   p1.creator = p2.creator and
   p2.project_id > p1.project_id

请注意,我使用的是>而不是!=,因此两个匹配的项目只能在一个方向上加入。否则每对项目将被返回两次。

您的基于联接的解决方案将是这样的:

SELECT distinct p1.project_id, p2.project_id
   FROM projects p1
   JOIN projects p2 on 
      p1.creator = p2.creator and
      p2.project_id > p1.project_id
   join skills sk1 on 
      sk1.project_id = p1.project_id
   join skills sk2 on 
      sk2.project_id = p2.project_id and
      sk1.skill = sk2.skill