标签: django-subquery

Django 1.11注释子查询聚合

这是一个前沿的功能,我目前正在解决这个问题并迅速流血.我想在现有的查询集上注释子查询聚合.在1.11之前执行此操作要么意味着自定义SQL,要么锤击数据库.这是这方面的文档,以及它的示例:

from django.db.models import OuterRef, Subquery, Sum
comments = Comment.objects.filter(post=OuterRef('pk')).values('post')
total_comments = comments.annotate(total=Sum('length')).values('total')
Post.objects.filter(length__gt=Subquery(total_comments))
Run Code Online (Sandbox Code Playgroud)

他们在总体上注释,这对我来说似乎很奇怪,但无论如何.

我正在努力解决这个问题,所以我正在把它煮回来,回到我有数据的最简单的现实世界的例子.我有Carparks包含很多Spaces.使用,Book?Author如果这让你更快乐,但是 - 现在 - 我只想使用Subquery*来注释相关模型的计数.

spaces = Space.objects.filter(carpark=OuterRef('pk')).values('carpark')
count_spaces = spaces.annotate(c=Count('*')).values('c')
Carpark.objects.annotate(space_count=Subquery(count_spaces))
Run Code Online (Sandbox Code Playgroud)

这给了我一个可爱的ProgrammingError: more than one row returned by a subquery used as an expression,在我的脑海里,这个错误非常有意义.子查询返回带有注释总计的空格列表.

这个例子表明会发生某种魔法,我最终会得到一个我可以使用的数字.但这不是在这里发生的?如何对聚合子查询数据进行注释?

嗯,有些东西被添加到我的查询的SQL中......

我建造了一个新的停车场/太空模型,它起作用了.所以下一步是弄清楚我的SQL中毒了什么.根据Laurent的建议,我看了一下SQL并尝试使它更像是他们在答案中发布的版本.这就是我发现真正问题的地方:

SELECT "bookings_carpark".*, (SELECT COUNT(U0."id") AS "c"
FROM "bookings_space" U0
WHERE U0."carpark_id" = ("bookings_carpark"."id")
GROUP BY U0."carpark_id", U0."space"
)
AS "space_count" FROM "bookings_carpark"; …
Run Code Online (Sandbox Code Playgroud)

django django-aggregation django-annotate django-subquery

28
推荐指数
6
解决办法
2万
查看次数

使用子查询来注释计数

请帮助我,我已经被困在这个问题上太久了:(

我想做的事:

我有这两个模型:

class Specialization(models.Model):
    name = models.CharField("name", max_length=64)
class Doctor(models.Model):
    name = models.CharField("name", max_length=128)
    # ...
    specialization = models.ForeignKey(Specialization)
Run Code Online (Sandbox Code Playgroud)

我想用具有该专业的医生数量来注释查询集中的所有专业。

到目前为止我的解决方案:

我经历了一个循环并做了一个简单的: Doctor.objects.filter(specialization=spec).count()然而事实证明这太慢而且效率低下。我读得越多,就越意识到使用此处SubQuery来筛选专业化的医生是有意义的OuterRef。这就是我想出的:

doctors = Doctor.objects.all().filter(specialization=OuterRef("id")) \
    .values("specialization_id") \
    .order_by()
add_doctors_count = doctors.annotate(cnt=Count("specialization_id")).values("cnt")[:1]

spec_qs_with_counts = Specialization.objects.all().annotate(
    num_applicable_doctors=Subquery(add_doctors_count, output_field=IntegerField())
)
Run Code Online (Sandbox Code Playgroud)

对于每个专业,我得到的输出仅为 1。代码只是用它来注释每个医生对象specialization_id,然后注释该组内的计数,这意味着它将是 1。

不幸的是,这对我来说并不完全有意义。在我最初的尝试中,我使用了一个聚合来进行计数,虽然它可以单独工作,但它不能作为 a 工作SubQuery,但我收到此错误:

This queryset contains a reference to an outer query and may only be used in a subquery.

我之前发布过这个问题,有人建议这样做Specialization.objects.annotate(count=Count("doctor"))

然而,这不起作用,因为我需要计算特定的医生查询集。

我已关注这些链接

但是,我没有得到相同的结果:

python django django-aggregation django-annotate django-subquery

10
推荐指数
2
解决办法
2万
查看次数

Django子查询和带有OuterRef的注释

OuterRef在Django 1.11子查询中使用annotate()时遇到问题.示例模型:

class A(models.Model):
    name = models.CharField(max_length=50)


class B(models.Model):
    a = models.ForeignKey(A)
Run Code Online (Sandbox Code Playgroud)

现在是一个带有子查询的查询(这没有任何意义,但说明了我的问题):

A.objects.all().annotate(
    s=Subquery(
        B.objects.all().annotate(
            n=OuterRef('name')
        ).values('n')[:1],
        output_field=CharField()
    )
)
Run Code Online (Sandbox Code Playgroud)

这会出现以下错误:

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "myapp/models.py", line 25, in a
    n=OuterRef('name')
  File ".virtualenv/lib/python2.7/site-packages/django/db/models/query.py", line 948, in annotate
    if alias in annotations and annotation.contains_aggregate:
AttributeError: 'ResolvedOuterRef' object has no attribute 'contains_aggregate'
Run Code Online (Sandbox Code Playgroud)

是否无法基于OuterRef注释子查询?


更新#1

找到一个解决方法,这将允许我现在继续前进,但它并不好.

class RawCol(Expression):

    def __init__(self, model, field_name, output_field=None):
        field = model._meta.get_field(field_name)
        self.table = model._meta.db_table
        self.column = field.column …
Run Code Online (Sandbox Code Playgroud)

django django-subquery

9
推荐指数
2
解决办法
1926
查看次数

Django 子查询抛出“用作表达式的子查询返回的多行”

我最近升级到 django 1.11,我想使用新发布的Subquery exrpession功能。有以下两种型号

class Project(models.Model):
    title = models.CharField(_("Project Name"), max_length=128)

class PrivateDonation(models.Model):
    project = models.ForeignKey(Project)
    value = models.DecimalField(_("value"),max_digits=19, decimal_places=2)
    ............
Run Code Online (Sandbox Code Playgroud)

我想获得一个用每个项目的私人捐赠价值总和注释的 Project 对象的查询集。我知道,还有其他方法可以实现这一点,而且我的应用程序已经有了一个可行的解决方案,但由于我正在学习此功能,因此我尝试了以下查询

private_donations = PrivateDonation.objects.filter(project=OuterRef('pk')).values('value')
private_donations_sum = private_donations.annotate(s=Sum('value')).values('s')
Project.objects.annotate(pd_sum=Subquery(queryset=private_donations_sum))
Run Code Online (Sandbox Code Playgroud)

但是上面的查询抛出异常

django.db.utils.ProgrammingError: more than one row returned by a subquery used as an expression
Run Code Online (Sandbox Code Playgroud)

唯一成功运行的查询是下面的查询。

private_donations = PrivateDonation.objects.filter(project=OuterRef('pk')).order_by().values('project')
private_donations_count = private_donations.annotate(c=Count('*')).values('c')
projects = Project.objects.annotate(space_count=Subquery(queryset=private_donations_count))
Run Code Online (Sandbox Code Playgroud)

但是,如果我在“private_donations”查询中选择“project”属性以外的任何其他内容,则会引发相同的错误

这是堆栈跟踪

The above exception was the direct cause of the following exception:
Traceback (most recent call last):
  File "<input>", line 1, in …
Run Code Online (Sandbox Code Playgroud)

django django-1.11 django-subquery

7
推荐指数
1
解决办法
4324
查看次数

Django条件子查询聚合

我的模型结构的简化示例是

class Corporation(models.Model):
    ...

class Division(models.Model):
    corporation = models.ForeignKey(Corporation)

class Department(models.Model):
    division = models.ForeignKey(Division)
    type = models.IntegerField()
Run Code Online (Sandbox Code Playgroud)

现在我想显示一个表格,显示公司,其中列将包含某种类型的部门数量,例如type=10.目前,这是通过Corporation模型上的帮助程序实现的,例如,检索那些帮助程序

class Corporation(models.Model):
    ...
    def get_departments_type_10(self):
        return (
            Department.objects
            .filter(division__corporation=self, type=10)
            .count()
        )
Run Code Online (Sandbox Code Playgroud)

这里的问题是,由于N + 1问题,这绝对是谋杀性能.

我试图用接近这个问题select_related,prefetch_related,annotate,和subquery,但我没有带能够得到我需要的结果.

理想情况下,查询Corporation集中的每个应该使用一个整数进行注释,该整数type_10_count反映了该类型的部门数量.

我确信我可以用原始sql做一些事情.extra(),但是文档宣布它将被弃用(我在Django 1.11上)

编辑:原始sql解决方案的示例

corps = Corporation.objects.raw("""
SELECT
*,
(
    SELECT COUNT(*)
    FROM foo_division div ON div.corporation_id = c.id
    JOIN foo_department dept ON dept.division_id = div.id
    WHERE dept.type …
Run Code Online (Sandbox Code Playgroud)

django django-annotate django-subquery

6
推荐指数
1
解决办法
1832
查看次数

Django:注释相关字段列表

我有一个公司和用户模型以及相关模型 CompanyRecruiter:

class CompanyRecruiter(models.Model):

    organization = models.ForeignKey(Company, related_name="company_recruiters")
    recruiter = models.ForeignKey(User, related_name="company_recruiters")
Run Code Online (Sandbox Code Playgroud)

我想注释作为招聘人员的用户的用户 ID 列表,以便公司稍后能够对其进行过滤:

Company.objects.annotate(some_stuff=some_other_stuff).values_list("user_ids", flat=True)
# [ [1, 2], [1, 56], [] ]
Run Code Online (Sandbox Code Playgroud)

我已经尝试使用自定义聚合和子查询但没有成功。我用的是postgres。

django django-aggregation django-annotate django-subquery

4
推荐指数
1
解决办法
3363
查看次数

Django 中带有多个结果的子查询的注释

我在我的项目中使用了 postgresql 数据库,我使用了 django文档中的以下示例。

from django.db.models import OuterRef, Subquery
newest = Comment.objects.filter(post=OuterRef('pk')).order_by('-created_at')
Post.objects.annotate(newest_commenter_email=Subquery(newest.values('email')[:1]))
Run Code Online (Sandbox Code Playgroud)

但不是最新的评论者电子邮件,我需要最后两封评论者的电子邮件。我改变了[:1][:2],但此异常引发:ProgrammingError: more than one row returned by a subquery used as an expression

django django-orm django-postgresql django-annotate django-subquery

0
推荐指数
1
解决办法
556
查看次数