2013-02-17 36 views
2

反向查詢,我有兩個型號:Django的由最後創建的對象

class SomeActivity(models.Model): 
    name = models.ChartField(max_length=100) 

class SomeStatus(models.Model): 
    name = models.CharField(max_length=100) 
    status = models.IntegerField(choises=STATUS_CHOISES) 
    some_activity = models.ForeignKey(SomeActivity, related_name='statuses') 

該活動的最後創建的狀態是當前的一個。爲了得到它,我用這個代碼:

try: 
    last_status = some_activity.statuses.latest('id') 
except: 
    last_status = None 

但問題是,當我想要返回所有Activities一個查詢,有last_status匹配status__in=[1, 2]

+0

什麼是名單[1,2]?來自SomeStatus對象的 – iMom0 2013-02-17 15:21:43

+0

狀態。我編輯的問題更清楚。 – UnLiMiTeD 2013-02-17 15:25:37

回答

2

該解決方案是有點扭曲,但我認爲它會工作:

from django.db.models import Max 

max_status_ids = SomeActivity.objects.filter(statuses__isnull=False).annotate(
       last_status_id=Max('statuses__id') 
      ).values_list('last_status_id', flat=True) 
status_satisfied_ids = SomeStatus.objects.filter(id__in=list(max_status_ids), 
       status__in=[1, 2]).values_list('id', flat=True) 
activities = SomeActivity.objects.filter(statuses__id__in=list(
       status_satisfied_ids)) 

我希望有一個更好的解決方案。


更新

嘗試

max_status_ids = SomeActivity.objects.annotate(last_status_id=Max('statuses') 
            ).values('last_status_id') 
activities = SomeActivity.objects.filter(statuses__in=max_status_ids, 
             statuses__status__in=(1,2)) 
  1. Django的自動生成時qsqs.values()qs.values_list()__in查找是使用的子查詢。因此就沒有必要以包裹查詢集瓦特/ list()(其還引入不必要的評價,因此不必要的中間SQLS)或寫flat=True內部qs.values_list()
  2. statuses__id__in查找內部activities已經引入了一個表加入,從而它的照從移動status__instatus_satisfied_ids轉換爲activities以利用連接。否則,status_satisfied_ids會引入額外的選擇。

或者您可以使用Window functions of PostgreSQL直接按排名位置過濾。

+1

@okm我在本節的最後閱讀了1.4的文檔,https://docs.djangoproject.com/en/1.4/ref/models/querysets/#,django建議使用mysql拆分查詢,我不知道它會更好,在第頁。 – iMom0 2013-02-19 02:25:14

+0

我不知道MySQL會達到什麼樣的性能水平,他們說這很糟糕。通常Postgres在這種工作上工作得很好 - 對於不那麼大的表格。對於大表,'in'子查詢仍然比[self-join]慢(http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per- group-in-sql /)或窗口函數。其次,大規模的''''子句表現不佳,無論是[MySQL](http://www.xaprb.com/blog/2006/06/28/why-large-in-clauses-are-problematic/)或Postgres。 – okm 2013-02-19 04:48:04

+1

只需在Postgres中測試兩個具有100k行的表格即可。 'in'子句中最慢:整體=> 3200ms,限制10 => 800ms,偏移50000限制10 => 2950ms;自連接:整體=> 650ms,限制10 => 0.3ms,偏移50000限制10 => 620ms;窗口功能:整體=> 510ms,限制10 => 310ms,偏移50000限制10 => 440ms。對於大型表格,我們可以看到上述方法性能都不是很好,如果操作頻繁,我們應該添加緩存或非規格化字段。 – okm 2013-02-19 05:02:24

相關問題