在三个表上使用内部联接并在单个查询中使用聚合

时间:2015-11-05 06:35:59

标签: python sql django django-orm

我有三个型号,

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且状态应为最大值每个身份。

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()

我尝试了这个查询。但它只返回一行,即具有最大状态的行。 我们可以修改它并返回每个id的结果。

3 个答案:

答案 0 :(得分:0)

您不像SQL一样使用Django ORM。如果我在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])

答案 1 :(得分: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])

答案 2 :(得分:0)

您可以使用annotationselect_related()来做您想做的事。

我根本没有对此进行过测试,但这是我要尝试的内容:

let array1 = [["aaa","bbb","ccc","ddd","eee"], ["fff","ggg","hhh","matched","iii"], ["lll","mmm","nnn","ooo","ppp"], ["666","777","888","999","000"] ] //4 elements

let array2 = [["111","222"], ["333","444"], ["matched","555"]] // 3 elements

let flat1 = Array(array1.flatten())       
let flat2 = Array(array2.flatten())

for (index1,object1) in flat1.enumerate() {
    for (index2,object2) in flat2.enumerate() {
        if object2 == object1 {
            print("index1 is: \(index1). Index 2 is \(index2)")
        }
    }
}

您可能需要将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级别,以确切了解您正在生成的SQL。