2013-02-17 70 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

相关问题