Python SQLAlchemy,选择至少有一个带升起标志的B的A
我有两张桌子:Python SQLAlchemy,选择至少有一个带升起标志的B的A,python,sql,postgresql,sqlalchemy,one-to-many,Python,Sql,Postgresql,Sqlalchemy,One To Many,我有两张桌子: class A(Base): id = Column(Integer, primary_key=True) class B(Base): id = Column(Integer, primary_key=True) a_id = Column(Integer, ForeignKey('a.id')) a = relationship(A) flag = Column(Boolean, default=False) 如您所见,B中的每个
class A(Base):
id = Column(Integer, primary_key=True)
class B(Base):
id = Column(Integer, primary_key=True)
a_id = Column(Integer, ForeignKey('a.id'))
a = relationship(A)
flag = Column(Boolean, default=False)
如您所见,B中的每个对象都与A中的一个对象相关,而且,B中的多个对象可以与A中的单个对象相关。
我需要选择所有至少有一个标志==False的相关B的A。
现在我在想这样的事情:
selection = session.query(A).\
join(B).\
filter(
B.a_id == A.id,
B.flag == False,
).\
group_by(A)
但有两件事我不确定:
拟合查询将使用半联接:
SELECT * FROM A
WHERE EXISTS (SELECT 1 FROM B WHERE a_id = A.id AND flag = FALSE);
为了快速实现这一点,您应该在B
上使用a_id
作为唯一或第一个表达式的任何索引。如果条件为“代码> >标志=false 是常见的,请考虑<强>部分索引< /强>,如:
CREATE INDEX b_some_nmae_idx ON b(a_id) WHERE flag = FALSE;
连接到
B
中所有匹配的行并再次聚合(就像您在问题中所做的那样)是一项毫无意义的工作<代码>存在可以在找到B
中的第一个匹配行后立即停止。在关系中添加一个backref
:
class B(Base):
# ...
a = relationship(A, backref="b_s")
然后@Erwin的SQL
版本的sqlalchemy
verino如下:
qry = session.query(A).filter(A.b_s.any(B.flag == False))
如果您不想或无法将backref
添加到关系中,下面将为简单的case生成相同的查询,但您应该关注生成的SQL
,以防您有更复杂的查询,因为连接可能需要更多的调整:
qry = (session.query(A).filter(
exists(select([1]).where(B.a_id == A.id).where(B.flag == False)))
)
谢谢你的回答。事实上,我知道如何在原始SQL中执行此操作:)我需要使用sqlalchemy执行相同的操作。@sennoy:正如我在回答中添加的:您现在的查询不是SQL中的最佳选择。是否可以不使用backref?