Запрос SQLAlchemy для объекта с количеством отношений

Допустим, у меня есть классы SQL Alchemy ORM:

class Session(db.Model):
  id = db.Column(db.Integer, primary_key=True)
  user_agent = db.Column(db.Text, nullable=False)

class Run(db.Model):
  id = db.Column(db.Integer, primary_key=True)

  session_id = db.Column(db.Integer, db.ForeignKey('session.id'))
  session = db.relationship('Session', backref=db.backref('runs', lazy='dynamic'))

И я хочу запросить по существу следующее:

((session.id, session.user_agent, session.runs.count())
  for session in Session.query.order_by(Session.id.desc()))

Однако это явно 1+n запросов, что ужасно. Как правильно это сделать, с 1 запросом? В обычном SQL я бы сделал это примерно так:

SELECT session.id, session.user_agent, COUNT(row.id) FROM session
LEFT JOIN rows on session.id = rows.session_id
GROUP BY session.id ORDER BY session.id DESC

person WirthLuce    schedule 20.10.2013    source источник
comment
Вы смотрели руководство по ORM, в частности раздел с пометкой Запросы с соединениями?   -  person Mark Hildreth    schedule 21.10.2013
comment
Да, я посмотрел на это, однако мне не ясно, как сделать соединение, за которым следует группа, и добавить счетчик в окончательный список столбцов.   -  person WirthLuce    schedule 21.10.2013


Ответы (2)


Создайте подзапрос, который группирует и подсчитывает идентификаторы сеансов из запусков, и присоединяйтесь к нему в окончательном запросе.

sq = session.query(Run.session_id, func.count(Run.session_id).label('count')).group_by(Run.session_id).subquery()
result = session.query(Session, sq.c.count).join(sq, sq.c.session_id == Session.id).all()
person davidism    schedule 21.10.2013

Целевой SQL может быть создан просто с помощью:

db.session.query(Session, func.count(Run.id)).\
    outerjoin(Run).\
    group_by(Session.id).\
    order_by(Session.id.desc())
person Ilja Everilä    schedule 12.04.2018