基本上我有一个SQLAlchemy查询,如下所示:
foos = Foo.query.filter(Foo.expiration < cutoff)
valid_foos = []
for foo in foos:
last_bar = foo.bars.order_by('created_at desc').first()
if last_bar.state != 'fatal':
valid_foos.append(foo)
目标是选择第一个相关酒吧状态不是&#34;致命&#34;的所有foos。看起来子查询可能对此有所帮助。但是,我正在努力掌握如何以这种方式表达last_bar = foo.bars.order_by('created_at desc').first()
。
答案 0 :(得分:0)
我认为最简单,最通用的方式是使用Hybrid Attributes
扩展名。当您按照以下方式扩展模型时:
class Foo(Base):
__tablename__ = "foo"
# ...
@hybrid_property
def last_bar_state(self):
_last_bar = self.bars.order_by(Bar.created_at.desc()).first()
return _last_bar.state
@last_bar_state.expression
def _last_bar_state_expression(cls):
q = (select([Bar.state.label("state")])
.where(Bar.foo_id == cls.foo_id)
.order_by(Bar.created_at.desc())
.limit(1)
).label("last_bar_state_sub")
return q
您可以在内存中以及查询中使用last_bar_state
:
foos = session.query(Foo).filter(Foo.expiration < cutoff)
foos = foos.filter(Foo.last_bar_state != 'fatal').all()
答案 1 :(得分:0)
使用子查询查找每个Foo的最新Bar。然后在查询Foo时使用它来连接和过滤Bar。
sub = db.session.query(
Foo.id,
db.func.max(Bar.created_at).label('latest')
).join(Foo.bars).group_by(Foo.id).subquery()
foos = db.session.query(Foo).join(Bar, db.and_(
Bar.foo_id == sub.c.id,
Bar.created_at == sub.c.latest
)).filter(Bar.status != 'fatal').all()
如果没有Bar,则不会选择Foo,您可以使用外部连接。