2011-10-31 90 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)。 –