2013-03-21 83 views
2

考慮下面的語句:的SQLAlchemy:joinedload +極限

p = db.query(Profile).options(joinedload('*')).filter_by(id=p.id).limit(1).one() 

我會得到一個子查詢+聯接,而不是一個 「純」 加盟:

SELECT [...] 
FROM (SELECT profile.id AS profile_id, ... 
FROM profile 
WHERE profile.id = %(id_1)s 
LIMIT %(param_1)s) AS anon_1 LEFT OUTER JOIN city AS city_1 ON city_1.id = anon_1.profile_city LEFT OUTER JOIN country AS country_1 ON country_1.id = city_1.country LEFT OUTER JOIN state AS state_1 ON country_1.id = state_1.country LEFT OUTER JOIN state AS state_2 ON state_2.id = city_1.state LEFT OUTER JOIN country AS country_2 ON country_2.id = state_2.country LEFT OUTER JOIN state AS state_3 ON state_3.id = city_1.state LEFT OUTER JOIN country AS country_3 ON country_3.id = state_3.country LEFT OUTER JOIN starred AS starred_1 ON anon_1.profile_id = starred_1.star LEFT OUTER JOIN profiletext AS profiletext_1 ON anon_1.profile_id = profiletext_1.profile LEFT OUTER JOIN starred AS starred_2 ON anon_1.profile_id = starred_2.idprofile LEFT OUTER JOIN photo AS photo_1 ON anon_1.profile_id = photo_1.profile LEFT OUTER JOIN gps AS gps_1 ON anon_1.profile_id = gps_1.idprofile 

但我真正需要的是:

SELECT ... 
FROM profile LEFT OUTER JOIN city AS city_1 ON city_1.id = profile.city LEFT OUTER JOIN country AS country_1 ON country_1.id = city_1.country LEFT OUTER JOIN state AS state_1 ON country_1.id = state_1.country LEFT OUTER JOIN state AS state_2 ON state_2.id = city_1.state  
LEFT OUTER JOIN country AS country_2 ON country_2.id = state_2.country LEFT OUTER JOIN state AS state_3 ON state_3.id = city_1.state LEFT OUTER JOIN country AS country_3 ON country_3.id = state_3.country LEFT OUTER JOIN starred AS starred_1 ON profile.id = starred_1.star LEFT OUTER JOIN profiletext AS profiletext_1 ON profile.id = profiletext_1.profile LEFT OUTER JOIN starred AS starred_2 ON profile.id = starred_2.idprofile LEFT OUTER JOIN photo AS photo_1 ON profile.id = photo_1.profile LEFT OUTER JOIN gps AS gps_1 
ON profile.id = gps_1.idprofile                                                  
WHERE profile.id = 4 
limit 1; 

即沒有子查詢。

數據庫:在PostgreSQL 9.2

+0

你使用的是哪個數據庫? – 2013-03-21 16:42:13

+0

postgresql 9.2。 – jbastos 2013-03-21 16:47:30

回答

2

這似乎是根據The Zen of Eager Loading

當使用加入預先加載,如果查詢包含 影響的行外返回加入改性劑預期的行爲,這樣的在使用 DISTINCT,LIMIT,OFFSET或同等語句時,完成的語句是 首先被包裝在子查詢中,並且專用於 的連接被加入預先加載的子查詢。 SQLAlchemy的加入 急於加載走多餘的一英里,然後進一步十英里,到 絕對保證它不會影響查詢的最終結果, 只有收集方式和相關對象被加載,不管 什麼格式該查詢是。

我意識到這是一個老問題,但是有沒有原因生成的SQL不起作用?

+0

這是否意味着如果在查詢中某處存在具有限制/ distinct/offset與查詢的查詢中某處的查詢,那麼該連接的數據被視爲子查詢? – adarsh 2014-07-21 11:42:31

+0

看來是這樣,是的。我不確定sqlalchemy的內部是否將它轉換爲[subqueryload](http://docs.sqlalchemy.org/en/latest/orm/loading.html#sqlalchemy.orm.subqueryload),但似乎就像它有相同的結果。 – Ben 2014-07-22 18:03:37