使用内连接和外连接创建查询时出现问题
我有以下模型(简化):
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()
当我执行这些查询中的任何一个时,我都会得到空值。我做错了什么?
I have the following model (simplified):
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')
I wanted to query all Relationships with a certain parent, and I also want to query votes made by a certain user on those Relationships. What I've tried:
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()
as well as:
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()
I get nulls when I do either of these queries. What am I doing wrong?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
只需打开 SQL 日志记录 (
echo=True
),您就会看到第一个选项的 SQL 查询结果类似于:如果您检查它,您会注意到子句
vote. rel_id=relationship.id
是JOIN
子句和WHERE
子句的一部分,这使得查询过滤掉那些Relationship
没有按要求投票的行用户。解决方案:
filter(Vote.rel_id == Relationship.id).
部分。filter(Vote.voter_id == thisuser.id)
的过滤器移出WHERE
并进入LEFT JOIN
子句:outerjoin(Vote, and_(Relationship.id == Vote.rel_id, Vote.voter_id == thisuser.id))
。Just turn on SQL logging (
echo=True
) and you will see that the resulting SQL query for the first option is something like:If you examine it, you will notice that the clause
vote.rel_id = relationship.id
is part of both theJOIN
clause and theWHERE
clause, which makes the query to filter out thoseRelationship
rows which do not have any votes by requested user.Solution:
filter(Vote.rel_id == Relationship.id).
part from the query.filter(Vote.voter_id == thisuser.id)
out ofWHERE
and into theLEFT JOIN
clause:outerjoin(Vote, and_(Relationship.id == Vote.rel_id, Vote.voter_id == thisuser.id))
.