【发布时间】:2020-07-09 15:06:07
【问题描述】:
我正在开发一个 Django 项目,在该项目上我有一个“A”对象 (A.objects.all()) 的查询集,并且我需要从“B”对象的子查询中注释多个字段。问题是 annotate 方法只能处理每个参数的一种字段类型(DecimalField、CharField 等),因此,为了注释多个字段,我必须使用类似的东西:
A.objects.all().annotate(b_id =Subquery(B_queryset.values('id')[:1],
b_name =Subquery(B_queryset.values('name')[:1],
b_other_field =Subquery(B_queryset.values('other_field')[:1],
... )
这是非常低效的,因为它为我要注释的每个字段在最终 SQL 上创建一个新的子查询/子选择。我想在它的 values() 参数上使用具有多个字段的相同 Subselect,并在 A 的查询集上对它们全部进行注释。我想使用这样的东西:
b_subquery = Subquery(B_queryset.values('id', 'name', 'other_field', ...)[:1])
A.objects.all().annotate(b=b_subquery)
但是当我尝试这样做(并访问第一个元素 A.objects.all().annotate(b=b_subquery)[0])时,它会引发异常:
{FieldError}Expression contains mixed types. You must set output_field.
如果我设置Subquery(B_quer...[:1], output_field=ForeignKey(B, models.DO_NOTHING)),我会得到一个数据库异常:
{ProgrammingError}subquery must return only one column
简而言之,整个问题是我有多个“属于”A的B,所以我需要使用子查询来为A.objects.all()中的每个A选择一个特定的B并将其附加到该A上,使用 OuterRefs 和一些过滤器(我只想要 B 的几个字段),这对我来说是一个微不足道的问题。
提前感谢您的帮助!
【问题讨论】:
-
查询是否低效取决于数据库引擎在发现公共子表达式并仅对其进行一次评估方面的能力。由于这是大型 SQL 查询中的一种典型模式,因此应该希望它们非常擅长这一点。
标签: python django django-rest-framework django-orm