我有两张桌子:
class Parent(Base):
__tablename__ = 'parents'
id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
min_quantity = sqlalchemy.Column(sqlalchemy.Integer, default=0, nullable=False)
children = sqlalchemy.orm.relationship('Child', backref=sqlalchemy.orm.backref('parent')
class Child(Base):
__tablename__ = 'children'
id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
expiration_date = sqlalchemy.Column(sqlalchemy.Date)
parent_id = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.ForeignKey('parents.id'))
最简单的方法是,只选择至少具有expiration_date<的min_quantity子项的Parent对象。 datetime.today()?
我可以查询每个Parent对象,然后进行列表理解:
parents = session.query(Parent).all()
ok_parents = [parent for parent in parents if len([child for child in parent.children if child.expiration_date < datetime.today()]) > parent.min_quantity]
但它感觉不像真正有效的代码。
我想我只能用一个好选项在一个查询中做到这一点,我怀疑我必须在查询中使用having(),但由于我对sqlachemy(和一般的SQL)的了解仍然有限,没有设法解决这个问题。
基本上,我对任何主张持开放态度。
答案 0 :(得分:0)
你的纠正是因为你可以使用HAVING条款。此外,您可以查询与子项一起加入的父项,按到期日期过滤,按父项ID分组,并按照与最小数量相关的每组行数过滤组:
ok_parents = session.query(Parent).\
join(Child).\
filter(Child.expiration_date < datetime.today()).\
group_by(Parent.id).\
having(func.count(1) > Parent.min_quantity).\
all()
上述查询中的一个警告是,由于内部联接,没有子项的父项不能成为结果。要解决此问题,您需要使用outerjoin(Child)
并通过没有子项(Child.id.is_(None)
)或到期日来过滤生成的行。