匹配多对多关系

时间:2018-12-10 17:58:19

标签: sql postgresql typescript typeorm

我有以下实体:

@Entity
class User {
    @ManyToMany(type => Group)
    @JoinTable()
    groups: Group[];
}

@Entity
class MediaObject {
    @ManyToMany(type => Group)
    @JoinTable()
    groups: Group[];
}

@Entity
class Group {
    // [...]
}

现在,我要选择与一个特定用户至少具有一个组的每个MediaObject。

示例:

User 1          MediaObject 1
-----------------------------
Group 1    |--- Group 2 
Group 2 ---|    Group 3

User 1 has at least one same group as MediaObject

如何为此建立一个sql查询?我使用typeorm构建查询,但每个sql查询都会有所帮助。另外,我想了解如何。 Typeorm这样连接表

LEFT JOIN "group" "groups" ON "groups"."id" = "media_groups"."groupId" 

2 个答案:

答案 0 :(得分:0)

使用简单的JOIN,您可以检索与用户共享至少一个组的MediaObject Id。比起使用IN来检索MediaObject

select *
from MediaObject mo
where mo.id in
(
    select moJoin.mediaObjectId
    from media_object_groups_group moJoin
    join user_groups_group uJoin on moJoin.groupId = uJoin.groupId
    where uJoin.userId = 1
)

答案 1 :(得分:0)

如果相同的MediaObject和相同的User之间可以有多个重叠的组,那么EXISTS的半联接可能比使用IN更快:

SELECT m.*
FROM   "MediaObject" m
WHERE  EXISTS (
   SELECT -- select list can be empty here
   FROM   user_groups_group         gu
   JOIN   media_object_groups_group gm USING ("groupId")
   WHERE  gu."userId" = 1
   AND    gm."mediaObjectId" = m.id
   );

否则,Radim's query在添加一些双引号后应该可以正常工作。

这假定引用完整性是通过外键约束来强制实施的,因此可以安全地依靠user_groups_group."userId"而不检查相应的用户是否存在。

使用"user"之类的reserved words或“ group”或CaMeL大小写的字符串作为标识符是不明智的。 需要双引号。 ORM通常在这方面服务不佳。参见: