У меня есть этот запрос в MySQL:
SELECT
O.id,
O.label,
A.name
FROM
organizations O
JOIN activities_area A JOIN assoc_organization_activities S ON
O.identifier = S.organization_id AND A.identifier = S.activities_area_id
ORDER BY
O.label
Я пытаюсь сделать это с помощью SQLAlchemy:
A = aliased(model.Activities, name='A')
S = aliased(model.AssocOrganizationsActivities, name='S')
O = aliased(model.Organizations, name='O')
organizations_query = session.query(O.id, O.label, A.name) \
.join(A) \
.join(S) \
.filter(O.identifier == S.organization_id) \
.filter(A.identifier == S.activities_area_id) \
.order_by(O.label) \
.all()
Но это дает мне эту ошибку:
InvalidRequestError: Could not find a FROM clause to join from. Tried joining to <class 'model.model.Activities'>, but got: Can't find any foreign key relationships between 'organizations' and 'activities_area'.
Таблица AssocOrganizationsActivities имеет только 3 поля: идентификатор, идентификатор организации в качестве внешнего ключа и идентификатор области действия в качестве внешнего ключа. Таким образом, обе столовые организации и действия связаны с AssocOrganizationsActivities.
Как заставить его работать?
Поменяйте порядок соединений. И ваш исходный SQL, и запрос страдают от того же самого, поэтому вместо этого:
organizations_query = session.query(O.id, ...) \
.join(S) \
.join(A) \
...
Предложения WHERE, которые вы добавляете в
...
.filter(O.identifier == S.organization_id) \
.filter(A.identifier == S.activities_area_id) \
...
похоже, что вы пытаетесь использовать синтаксис pre ANSI join, но смешиваются с ANSI-соединениями. Они полностью избыточны в том, что SQLAlchemy может выводить предложения ON для объединений на основе отношений внешнего ключа между моделями. Исходный SQL нарушен аналогичным образом в том, что
FROM
organizations O
JOIN activities_area A JOIN ...
вообще не имеет предложения ON между O и A, кроме того, нет очевидного способа присоединиться к ним без первого присоединения к таблице ассоциаций. В общем:
organizations_query = session.query(O.id, O.label, A.name) \
.join(S) \
.join(A) \
.order_by(O.label) \
.all()