2011-10-31 22 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() 

を、私はこれらのクエリのいずれかを実行したときに、私はnullを取得します。私は間違って何をしていますか?

答えて

2

ちょうどSQLロギング(echo=True)をオンにすると、あなたは、最初のオプションのために結果のSQLクエリのようなものであることがわかります:あなたはそれを調べる場合は、WHERE句vote.rel_id = relationship.idが一部であることがわかります

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 

JOIN句と句の両方を使用して、要求されたユーザーが投票を持たないRelationship行を除外するクエリを作成します。

ソリューション:

  1. は、クエリからの冗長filter(Vote.rel_id == Relationship.id).の部分を削除します。
  2. 編集-1outerjoin(Vote, and_(Relationship.id == Vote.rel_id, Vote.voter_id == thisuser.id)):またWHERE外とLEFT JOIN句にユーザfilter(Vote.voter_id == thisuser.id)のフィルタを移動させる(取り除きます)。
+0

ありがとう、それではエラーになりません。しかし、私が情報を抽出しようとすると、Voteがnullの行は返されません。左外部結合について理解しているものから、右結合がNULLであるかどうかに関係なく、行が返されます。私は間違って何をしていますか? get_relationships(thisthing、thisuser)内のb: #Do this –

+0

LEFT OUTER JOINを使用すると、結合の左側( 'Relationship')が返されます。右側( 'Vote')に一致する行は見つかりませんが、' NULL/None'が返されます。代わりに何を見たいですか? – van

+0

私はそれを左外部結合のように動作させたいと思いますが、今はouterjoin()を使用していても、内部結合のように動作しています。 (Vote)が見つからない場合は、(NULL)を除く必要がありますが、(Relationship)は返されません。 –

関連する問題