django,如何在外部查询中使用子查询值

问题描述 投票:0回答:1

我有一个使用子查询中的值的查询。虽然我可以在 django 中编写子查询,但无法编写主查询。这是一个小例子(模式是 department <-- person <-- device --> model):

SELECT 
    department.id,
    AVG(subquery.typeofdevices_count) AS avg_typeofdevice_count_per_department
FROM department 
INNER JOIN person ON (department.id = person.department_id) 
INNER JOIN device ON (person.id = device.person_id) 
INNER JOIN (
    SELECT 
        model.id AS id,
        count(DISTINCT device.id) filter (WHERE device.type = 'something') AS typeofdevices_count,
    FROM model 
    LEFT OUTER JOIN device ON (model.id = device.model_id)
    WHERE ('some-conditions...')
    GROUP BY model.id,

) AS subquery ON (subquery.id = device.model_id)

如您所见,外部查询使用内部值typeofdevices_count,同时与子查询id连接。

关于内部查询非常简单:

subquery = Model.objects.annotate(typeofdevices_count=
               Count('device__location_id',
                     filter=Q(device__type='something'), 
                     distinct=True
               )
            ).filter('some-conditions...').values('id', 'typeofdevices_count')

主要查询怎么样?我尝试了以下方法:

Department.objects.annotate(avg_typeofdevice_count_per_department=
    Avg('persons__devices__model__typeofdevices_count',
        filter=Q(persons__devices__model__in=subquery)
    )
).values('id', 'avg_typeofdevice_count_per_department')

但是我得到了这个错误,它似乎无法识别子查询注释typeofdevices_count

FieldError:无法将关键字“typeofdevices_count”解析为字段。选项有:...

你能帮我吗?

sql django django-orm
1个回答
0
投票

如果不查看模型以及关系存在哪些外键,就很难告诉您任何信息。

根据您提供的内容:

department <-- person <-- device --> model
,这部分是错误的,您不能直接从
Department
引用到
persons
关系,在您的查询中:

Department.objects.annotate(avg_typeofdevice_count_per_department=
    Avg('persons__devices__model__typeofdevices_count',
        filter=Q(persons__devices__model__in=subquery)
    )
).values('id', 'avg_typeofdevice_count_per_department')

此外,你的原始

SQL
并不完全正确,但从中可以清楚地看出你想做什么。这是这样的,可以给出用
django ORM
写的预期结果:

from django.db import models

subquery = (
    Device.objects
    .select_related('model')
    .filter(
        #  device.person_id=person.id
        person_id=models.OuterRef('id'),
        #  and other conditions
    )
    #  group by model.id
    .values('model__id')
    .annotate(
        typeofdevices_count=models.Count(
            'id',
            filter=models.Q(type='something'),
            distinct=True,
        ),
    )
    .values('typeofdevices_count')
)
queryset = (
    Person.objects
    .select_related('department')
    .annotate(devices_count=models.Subquery(subquery))
    .values('department__id')
    .annotate(avg_typeofdevice_count_per_department=models.F('devices_count'))
    .values('department__id', 'avg_typeofdevice_count_per_department')
)

我可能在某个地方犯了错误。你应该检查一下!它将生成与您的

SQL
略有不同的查询,但结果应该符合预期 - 每个部门计算某种类型设备的平均值。

© www.soinside.com 2019 - 2024. All rights reserved.