2011-10-31 60 views
0

我有以下的模型(简体):创建与内部查询有问题加入与外连接

class User(Base): 
    __tablename__ = 'user' 
    id = Column(Integer, primary_key=True) 

class Thing(Base): 
    __tablename__ = 'thing' 
    id = Column(Integer, primary_key=True) 

class Relationship(Base): 
    __tablename__ = 'relationship' 
    id = Column(Integer, primary_key=True) 
    parent_id = Column(Integer, ForeignKey('thing.id')) 
    parent = relationship('Thing', backref='parentrelationships', primaryjoin = "Relationship.parent_id == Thing.id") 
    child_id = Column(Integer, ForeignKey('thing.id')) 
    child = relationship('Thing', backref='childrelationships', primaryjoin = "Relationship.child_id == Thing.id") 

class Vote(Base) 
    __tablename__ = 'vote' 
    id = Column(Integer, primary_key=True) 
    rel_id = Column(Integer, ForeignKey('relationship.id')) 
    rel = relationship('Relationship', backref='votes') 
    voter_id = Column(Integer, ForeignKey('user.id')) 
    voter = relationship('User', backref='votes') 

我想查询有一定的母公司所有的关系,我也想查询票由某个用户在这些关系上创建的。我试过什么:

def get_relationships(thisthing, thisuser): 
    return DBSession.query(Relationship, Vote).\ 
     filter(Relationship.parent_id == thisthing.id).\ 
     outerjoin(Vote, Relationship.id == Vote.rel_id).\ 
     filter(Vote.voter_id == thisuser.id).\ 
     filter(Vote.rel_id == Relationship.id).\ 
     all() 

还有:

def get_relationships(thisthing, thisuser): 
    session = DBSession() 
    rels = session.query(Relationship).\ 
     filter(Relationship.parent_id == thisthing.id).\ 
     subquery() 
    return session.query(rels, Vote).\ 
     outerjoin(Vote, rels.c.id == Vote.rel_id).\ 
     filter(Vote.voter_id == thisuser.id).\ 
     all() 

我得到空当我做这两种查询。我究竟做错了什么?

回答

2

只需打开SQL日志(echo=True),你会看到,第一个选项生成的SQL查询是这样的:

SELECT relationship.id AS relationship_id, relationship.parent_id AS relationship_parent_id, relationship.child_id AS relationship_child_id, vote.id AS vote_id, vote.rel_id AS vote_rel_id, vote.voter_id AS vote_voter_id 
FROM relationship LEFT OUTER JOIN vote ON relationship.id = vote.rel_id 
WHERE relationship.parent_id = ? AND vote.voter_id = ? AND vote.rel_id = relationship.id 

如果你检查它,你会发现该条款vote.rel_id = relationship.id是部分的JOIN子句和WHERE子句,这使查询过滤掉那些没有被请求的用户投票的那些Relationship行。

解决方案:

  1. 删除冗余filter(Vote.rel_id == Relationship.id).部分从查询。
  2. 编辑-1:也移动(删除)的过滤器为用户filter(Vote.voter_id == thisuser.id)WHERE并进入LEFT JOIN子句:outerjoin(Vote, and_(Relationship.id == Vote.rel_id, Vote.voter_id == thisuser.id))
+0

谢谢你,现在没有错误。但是,当我尝试提取信息时,Vote为null的行不会返回。根据我对左外连接的理解,无论右连接是否为空,都应返回该行。我究竟做错了什么?我使用以下方法提取对象: for a,b in get_relationships(thisthing,thisuser): #执行此操作 –

+0

使用'LEFT OUTER JOIN',将返回连接的左侧('Relationship'),如果找不到右侧('Vote')的匹配行,但会返回“NULL/None”。你想看到什么? – van

+0

我希望它像一个左外连接,但现在它的行为像一个内连接,即使我正在使用outerjoin()。 (关系)没有被返回时(投票)没有找到,虽然我应该除了(NULL)。 –