Возможно, вы нашли пределы Query.from_self()
:
Функция автоматического наложения имен работает только в режиме limited ,для простых фильтров и заказов.Более амбициозные конструкции, такие как ссылки на сущность в соединениях, должны предпочитать использовать явные объекты подзапроса, обычно используя метод Query.subquery()
для создания явного объекта подзапроса.Всегда проверяйте структуру запросов, просматривая SQL, чтобы убедиться, что конкретная структура выполняет то, что ожидалось!
В общем случае «автокорреляция» SQLAlchemy рассматривает объекты FROM для корреляции только из непосредственного вмещающего запроса и если требуются более глубокие уровни вложенности, должна использоваться явная корреляция.
С другой стороны, в вашем случае это не поможет.Добавление вызова к Query.correlate()
по какой-то причине не нарушает границы Query.from_self()
, хотя их совместное использование даже упоминается в документации:
Аргументы корреляциивступают в силу в тех случаях, когда используется Query.from_self()
, или когда подзапрос, возвращаемый Query.subquery()
, встроен в другую конструкцию select()
.
Решение состоит в использовании явных подзапросов:
In [65]: sq = session.query(Entity.flag, Entity.timestamp).\
...: distinct(Entity.original_id).\
...: order_by(Entity.original_id, Entity.id.desc()).\
...: filter(Entity.ref_id == E.ref_id).\
...: correlate(E).\
...: subquery()
In [66]: q = session.query(E).\
...: filter(E.user_id == 123).\
...: filter(session.query(sq.c.flag).
...: order_by(sq.c.timestamp.desc()).
...: limit(1).
...: as_scalar()).\
...: order_by(E.timestamp)
...:
In [67]: print(q.statement.compile(dialect=postgresql.dialect()))
SELECT e.id, e.ref_id, e.timestamp, e.original_id, e.user_id, e.flag
FROM entity AS e
WHERE e.user_id = %(user_id_1)s AND (SELECT anon_1.flag
FROM (SELECT DISTINCT ON (entity.original_id) entity.flag AS flag, entity.timestamp AS timestamp
FROM entity
WHERE entity.ref_id = e.ref_id ORDER BY entity.original_id, entity.id DESC) AS anon_1 ORDER BY anon_1.timestamp DESC
LIMIT %(param_1)s) ORDER BY e.timestamp