2015-11-05 58 views
1

我有三个型号,使用内部联接三个表,并聚集在一个单一的查询

class A(models.Model): 
    code=models.CharField(max_length=9,unique=True) 

class B(models.Model): 
    submitted_by = models.ForeignKey(D) 
    a = models.OneToOneField(A) 
    name = models.CharField(max_length=70,blank=True,default='') 


class C(models.Model): 
    status = models.PositiveSmallIntegerField() 
    status_time = models.DateTimeField(auto_now_add=True) 
    a = models.ForeignKey(A) 

我需要查询,这样我可以获取代码(从模型A),名称(从B型)和状态时间(来自模型C)和状态(来自模型C),其中submitted_by_id = 1并且状态对于每个id应该是最大的。

的SQL是:

SELECT A.code ,B.name,C.status,C.status_time FROM `A` INNER JOIN `B` on A.id=B.a_id INNER JOIN `C` on A.id=C.a_id where B.submitted_by_id=1 and C.status_time=(se lect max(C.status_time) from `C` pipeline where C.a_id=A.id) 

如果任何人能帮助我的Django的ORM。 我无法理解如何在单个查询中一起使用内部连接,聚合和子查询。

编辑:

B.objects.filter(submitted_by_id=1).values('name','a__code','a__c__status_time','a__c__status').order_by('-a__c__status').first() 

我想这query.But它只返回一行即具有最高地位排。 我们可以修改它并返回每个ID的结果。

+0

仍在寻找答案。我需要这个查询来创建一个数据表视图。 –

回答

0

您不使用Django ORM(如SQL)。如果我理解正确,你在Django ORM查询看起来像:

result = [] 
bs = B.objects.filter(submitted_by_id=1) 
for b in bs: 
    a = b.a 
    c = C.objects.filter(a=a).order_by('-status').first() 
    result.append([a.code, b.name, c.status, c.status_time]) 
+0

thnx。有用。但我需要在单个查询中执行此操作。我已经尝试过SQL,它工作正常。即使你的答案是完美的。但是如果你能帮我在单个查询中做到这一点。如果不可能,请解释为什么 –

+0

不幸的是,这是不可能的,因为在Django ORM中,你不能'加入'不同的模型。但是,您可以使用'connection'对象并执行原始的'SQL'查询。这里有一个文档链接:https://docs.djangoproject.com/en/1.8/topics/db/sql/#connections-and-cursors – Nhor

+0

我更新了我的问题与编辑。可能是如果你可以解决问题,否则我会接受你的答案并继续前进。如果你能为此提供关于原始SQL的建议,那将会更好。 –

0

也许后续可以帮助:

results = [] 
b_set = B.objects.filter(submitted_by__id=1) 
for b in b_set: 
    c = C.objects.filter(a__b=b).order_by('-status_time').first() 
    results.append([c.a.code, c.a.b.name, c.status, c.status_time]) 
+0

我想在单个查询中执行此操作。 –

0

你或许可以使用annotationselect_related()做你想做什么。

我没有测试过这在所有的,但这里是我想尝试:

from django.db.models import F 
from django.db.models import Max 

annotated_c = C.objects.annotate(last_status_time=Max('a__cs__status_time')) 
last_c = annotated_c.filter(status_time=F('last_status_time'), 
          a__b__submitted_by_id=1) 

for c in last_c.select_related('a', 'a__b'): 
    print c.a.code, c.a.b.name, c.status_time 

您可能需要增加related_name到外键。

django.db记录器设置为DEBUG级别以准确查看您正在生成的SQL。

+0

还有一个他想要在“submitted_by_id”= 1上过滤的条件。也许你可以添加这个。 –

+0

感谢您的支持,@FullOfQuestions,我现在添加了缺少的过滤器。 –