我有两张桌子:
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的单个对象相关。
我需要选择所有A至少有一个相关B且标志为== False的A。
现在我正在考虑这样的事情:
selection = session.query(A).\
join(B).\
filter(
B.a_id == A.id,
B.flag == False,
).\
group_by(A)
但我不确定两件事:
如果此查询正确无误? (我正在处理大量数据,测试这个数据非常复杂。)
如果从sqlalchemy哲学的角度来看这个查询是正确的吗? (我是新手)。
答案 0 :(得分:1)
拟合查询将使用EXISTS
半连接:
SELECT * FROM A
WHERE EXISTS (SELECT 1 FROM B WHERE a_id = A.id AND flag = FALSE);
为了加快速度,你应该在B
上只有a_id
的任何索引,只有flag = FALSE
或第一个表达式。如果条件CREATE INDEX b_some_nmae_idx ON b(a_id) WHERE flag = FALSE;
的查询很常见,请考虑部分索引,如:
B
加入所有匹配的EXISTS
行并再次聚合(就像你在问题中一样)是很多毫无意义的工作。只要找到B
中的第一个匹配行,{{1}}就会停止。
答案 1 :(得分:1)
在关系中添加backref
:
class B(Base):
# ...
a = relationship(A, backref="b_s")
然后@ Erwin sqlalchemy
版本的SQL
verino如下:
qry = session.query(A).filter(A.b_s.any(B.flag == False))
如果您不想或不能将backref
添加到关系中,以下内容将针对简单案例生成相同的查询,但是如果您有更多内容,则应密切关注生成的SQL
复杂的查询,因为连接可能需要更多调整:
qry = (session.query(A).filter(
exists(select([1]).where(B.a_id == A.id).where(B.flag == False)))
)