Краткий ответ: SQLAlchemy работает должным образом.
Ключевым виновником является тот факт, что при запросе сопоставленной модели вы получите экземпляры модели в виде результат. Если одна и та же модель возвращается несколько раз, SA будет возвращать каждую только один раз, и поэтому у вас возвращается только 1 строка вместо ожидаемых 3.
Это можно увидеть по разнице в SQL, который вы создаете (select * ...
) против того, который создает для вас SA (select items.*
; SA не создает *
, но дело в том, что он выбирает только из таблицы items
.
Решение состоит в том, чтобы добавить и другие сущности к query(...)
, которые должны быть возвращены:
final_items = aliased(Items, name="FinalItems")
proj = (
session
.query(Items, Attribution, final_items) # IMPORTANT !!!
.join(Attribution, ( (Items.name=="upper_third") & (Attribution.link_id_m==Items.linkid) ))
.join(final_items, final_items.linkid==Attribution.link_id_d)
)
Выполнение, как показано ниже:
for l in proj.all():
print(l)
# print(l.Items, l.Attribution, l.FinalItems) # also can access models using names.
... приведет к список tuple(Items, Attribution, Items)
:
(<Items(id=5, linkid=1, name='upper_third', project=1)>, <Attribution(id=1, link_id_d=2, link_id_m=1)>, <Items(id=2, linkid=2, name='lower_first', project=2)>)
(<Items(id=5, linkid=1, name='upper_third', project=1)>, <Attribution(id=1, link_id_d=2, link_id_m=1)>, <Items(id=4, linkid=2, name='lower_second', project=2)>)
(<Items(id=5, linkid=1, name='upper_third', project=1)>, <Attribution(id=1, link_id_d=2, link_id_m=1)>, <Items(id=6, linkid=2, name='lower_third', project=2)>)
Если вы действительно хотите, чтобы столбцы были возвращены, как в вашем примере, вы можете выполнить statement
запроса. Код ниже
for row in session.execute(proj.statement):
print(row)
вернет:
(5, 'upper_third', 1, 1, 1, 2, 1, 2, 'lower_first', 2, 2)
(5, 'upper_third', 1, 1, 1, 2, 1, 4, 'lower_second', 2, 2)
(5, 'upper_third', 1, 1, 1, 2, 1, 6, 'lower_third', 2, 2)