SQLAlchemy: несколько подсчетов в одном запросе
Я с трудом оптимизирую свои запросы SQLAlchemy. Мои знания SQL очень просты, и я просто не могу получить то, что мне нужно, из документации по SQLAlchemy.
Предположим следующее очень простое отношение один ко многим:
class Parent(Base):
__tablename__ = "parents"
id = Column(Integer, primary_key = True)
children = relationship("Child", backref = "parent")
class Child(Base):
__tablename__ = "children"
id = Column(Integer, primary_key = True)
parent_id = Column(Integer, ForeignKey("parents.id"))
naughty = Column(Boolean)
Как я мог:
Запрос кортежей(Parent, count_of_naughty_children, count_of_all_children)
для каждого родителя?После приличного времени, проведенного в поиске, я нашел, как запросить эти значения отдельно:
# The following returns tuples of (Parent, count_of_all_children):
session.query(Parent, func.count(Child.id)).outerjoin(Child, Parent.children).\
group_by(Parent.id)
# The following returns tuples of (Parent, count_of_naughty_children):
al = aliased(Children, session.query(Children).filter_by(naughty = True).\
subquery())
session.query(Parent, func.count(al.id)).outerjoin(al, Parent.children).\
group_by(Parent.id)
Я пытался объединить их по-разному, но не смог получить то, что я хочу.
Опросите всех родителей, у которых более 80% непослушных детей? Редактировать: непослушный может быть NULL.Я полагаю, что этот запрос будет основан на предыдущем запросе с фильтрацией по непослушному / всему отношению.
Любая помощь приветствуется.
РЕДАКТИРОВАТЬ : Благодаря помощи Антти Хаапала я нашел решение второго вопроса:
avg = func.avg(func.coalesce(Child.naughty, 0)) # coalesce() treats NULLs as 0
# avg = func.avg(Child.naughty) - if you want to ignore NULLs
session.query(Parent).join(Child, Parent.children).group_by(Parent).\
having(avg > 0.8)
Он находит средний, если детскийnaughty
переменная, рассматривая False и NULL как 0, а True как 1. Протестировано с бэкэндом MySQL, но должно работать и на других.