2013-07-17 59 views
2

我希望能够通过SQLAlchemy中的多个多对多关系进行查询。通过SQLAlchemy选择多个多对多关系

我有用户,这些用户与组关联到角色。所有的关联都是多对多的。我想通过组获得与用户关联的角色列表。

这里是我的条纹向下的模型:

class User(Model): 
    id = Column(Integer) 
    groups = relationship('Group', secondary=user_group) 

class Group(Model): 
    id = Column(Integer) 
    roles = relationship('Role', secondary=role_group) 

class Role(Model): 
    id = Column(Integer) 

我有什么SQL将被用来粗略的想法:

select distinct role.* from role, role_group 
where role.id = role_group.role_id 
    and role_group.group_id in 
    (select "group".id from "group", user_group 
    WHERE user_group.user_id = 1 
     and "group".id = user_group."group.id") 

,但我有一个很难搞清楚如何把这种到SQLAlchemy中...并且我不确定即使这里的SQL是执行此操作的最佳方法。

回答

3

试试这个

s = Session() 
s.query(Role).join(User.groups).join(Group.roles).filter(User.id==1).all() 

它会产生下面的SQL查询

SELECT role.id AS role_id 
FROM user 
JOIN user_group AS user_group_1 ON user.id = user_group_1.user_id 
JOIN "group" ON "group".id = user_group_1.group_id 
JOIN role_group AS role_group_1 ON "group".id = role_group_1.group_id 
JOIN role ON role.id = role_group_1.role_id 
WHERE user.id = 1; 

但是SQLAlchemy的将只返回不同的角色(如果你将查询Role.id然后SQLAlchemy的会返回一个SQL查询实际上返回)。

+0

完美。这正是我所期待的。如果您在原始问题中注意到我确实需要不同的角色(请参阅SQL)。此外,这似乎比我上面写的更适当的SQL。谢谢。 – bpedman

0

我的确找到了解决我自己的问题的方法,它可以生成接近我正在寻找的SQL。不过,我相信zaquest的答案要好得多,而且会用到。这只是为了后代的缘故。

这里是我想出了查询:

s = Session() 
s.query(Role).join(Role.groups).filter(
     Group.id.in_(s.query(Group.id).join(User.groups) 
       .filter(User.id == self.id))) 

这将生成的SQL语句

SELECT role.id AS role_id 
FROM role JOIN role_group AS role_group_1 ON role.id = role_group_1.role_id 
JOIN "group" ON "group".id = role_group_1.group_id 
WHERE "group".id IN 
    (SELECT "group".id AS group_id 
    FROM "user" JOIN user_group AS user_group_1 ON "user".id = user_group_1.user_id 
    JOIN "group" ON "group".id = user_group_1."group.id" 
    WHERE "user".id = :id_1) 

这与我一直在寻找的SQL。我忘记的关键是我可以在SQLAlchemy中使用另一个查询作为in运算符的一部分。