2011-05-30 48 views
1

我需要實現類似在同一層級

(SELECT table1.*, val=2 FROM table1 INNER JOIN table2 ON table1.id = table2.id WHERE some_condition) 
UNION 
(SELECT table1.*, val=3 FROM table1 INNER JOIN table3 ON table1.id = table3.id WHERE some_condition) 

(SELECT val1, val2, val3, val=2 FROM table2 WHERE some_condition) 
UNION 
(SELECT val1, val2, val3, val=3 FROM table3 WHERE some_condition) 

在不同類別之間的Django的ORM的語法使用UNION即具有類'table1','table2'和'table3',其中table2和table3是從table1派生的,我需要使用其他字段選擇它們。問題是我願意避免使用原始的sql查詢,因爲some_condition應該是可重用的。如果我嘗試使用額外的它抱怨我使用.extra

回答

0

我決定移植到sqlalchemy - 我的問題非常適合django,而我對tg2更加開心(說 - 這並不意味着django不好 - 它不適合我的任務)。

0

你可以把它改寫爲子查詢:

select val1, val2, val3, val4 
from (
    SELECT val1, val2, val3, val=2 as val4 FROM table2 
    UNION 
    SELECT val1, val2, val3, val=3 as val4 FROM table3 
    ) t 
where some_condition 

警惕但是,因爲它不一定做的最好的事情。

它可能令人滿意,因爲你避免重寫條件,但對於查詢規劃者來說,這兩個查詢可能是非常不同的動物。 Postgres有時足夠聰明,可以將條件注入到子語句中,但是我從來沒有看到過這種情況的一種情況是子語句具有任何類型的聚合。

具體而言,如果條件放置在外(如上所述),則將從附加兩個整個表開始。然後,您會聚合它們以消除重複項(這是您通過使用union all而不是union,而不是使用來避免的一個步驟),並且您最終會篩選出符合條件的結果集中的行。

相比之下,當放置在各個位內時,您將追加並排序兩組較小的行。它會更快,消耗更少的內存。

簡而言之,儘可能早地在您的查詢中過濾行。

+0

在這個查詢中'some_condition'的重複沒有問題 - 問題是1.它被用在許多其他查詢中,並可能返回大數據集,因此我不想將它緩存在內存2中。'some_condition'本身用於其他查詢。 – 2011-05-31 10:11:21

1

如果您試圖在.execute調用之外編寫此JOIN/UNION,您將花費大量時間與django ORM API對抗。如果這將是非常普遍的,請考慮使用VIEW,然後從新創建的VIEW中簡單地執行SELECT