根据尊重某些标准的孩子的数量过滤父母

时间:2017-09-26 16:56:07

标签: python sqlalchemy

我有两张桌子:

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)的了解仍然有限,没有设法解决这个问题。

基本上,我对任何主张持开放态度。

1 个答案:

答案 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))或到期日来过滤生成的行。