2012-07-23 142 views
1

這裏是我的架構:力INNER JOIN Django的查詢

市 - >攝影師

我試圖讓至少有一個攝影師城市的列表,並返回攝影師計數城市。

這是我的工作的查詢集:

City.objects.annotate(photographer_count=aggregates.Count('photographers')).filter(photographer_count__gt=0).order_by('-photographer_count') 

這工作完全按照我希望它太,但出於某種原因Django的選擇,使與左外城/攝影師之間加盟加盟。如果我抓取SQL文本並將「left outer」更改爲「inner」,則查詢從約11秒變爲200ms,結果相同。

我試着在註釋前面放一個過濾器來提示Django它應該是內部加入,但那並不奏效。

任何Django查詢voodoo我可以執行此操作來獲得內部連接?我意識到我可以使用直接的SQL,但寧願通過ORM。

+0

如果有人想知道我做了什麼可怕的事情做了這項工作,我結束了字符串替換爲「內」的「外」。 Gross,但至少我的查詢仍然會隨着未來架構調整而擴大。 – jarcoal 2012-08-17 18:31:56

回答

1

您通常無法對Django執行的查詢和連接進行這種級別的控制。

Django並沒有做很聰明的事情,例如注意到過濾條件意味着您可以用INNER JOIN在這一點上逃脫 - 它必須產生在一般情況下正確的查詢,在這種情況下意味着盡我所知,左外連接。

所以你可能會需要原始的SQL。

3

默認情況下,會生成一個LEFT JOIN,這樣即使對於攝影師數量爲零的城市,Django也可以獲得行數。如果您知道你不想這些,這裏有一個技巧,迫使Django的生成INNER JOIN

City.objects.filter(
    photographer__isnull=False 
).annotate(
    photographer_count=aggregates.Count('photographers') 
).filter(
    photographer_count__gt=0 
).order_by(
    '-photographer_count' 
) 

具體而言,第一濾波器告訴Django,一個INNER JOIN是安全的。它必須來電annotate()之前。