简体   繁体   English

Django:在Queryset上使用Annotate,Count和Distinct

[英]Django: Using Annotate, Count and Distinct on a Queryset

Here's my database query: 这是我的数据库查询:

results = Attachments.objects.filter(currency='current').annotate(num_attachments=Count('article_id')).order_by("num_attachments").distinct('article_id')

The query broken down as follows (as I understand it): 查询细分如下(据我所知):

  • First filter is current Attachments that are "current". 第一个过滤器是“当前”的当前附件。
  • Then to count the number of those Attachments with a certain 'article_id'. 然后使用某个'article_id'计算这些附件的数量。
  • Then to annotate each Attachment with the number of Attachment with the number of those that have article_id in common. 然后使用附件编号注释每个附件,其中包含具有共同的article_id的编号。
  • Then to rank based on the number of attachments. 然后根据附件数量排名。
  • Then, paring down the list with distinct, so that there's one Attachment object for each article_id value. 然后,使用distinct减去列表,以便每个article_id值都有一个Attachment对象。

I am running this on PostgreSQL, so according to the Django docs , I'm fine to run distinct() based on a field. 我在PostgreSQL上运行它,所以根据Django 文档 ,我可以根据字段运行distinct()。

There is no error when I execute the query, but when I try to iterate or even print the results the following error is thrown by Django debug: 执行查询时没有错误,但是当我尝试迭代甚至打印结果时,Django调试会抛出以下错误:

NotImplementedError at /function/
annotate() + distinct(fields) not implemented.

The more detailed traceback from the interactive prompt is: 交互式提示中更详细的回溯是:

  File "<console>", line 1, in <module>
  File "/Users/Pat/.virtualenvs/envsp/lib/python2.7/site-packages/django/db/models/query.py", line 118, in _result_iter
    self._fill_cache()
  File "/Users/Pat/.virtualenvs/envsp/lib/python2.7/site-packages/django/db/models/query.py", line 875, in _fill_cache
    self._result_cache.append(self._iter.next())
  File "/Users/Pat/.virtualenvs/envsp/lib/python2.7/site-packages/django/db/models/query.py", line 291, in iterator
    for row in compiler.results_iter():
  File "/Users/Pat/.virtualenvs/envsp/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 763, in results_iter
    for rows in self.execute_sql(MULTI):
  File "/Users/Pat/.virtualenvs/envsp/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 808, in execute_sql
    sql, params = self.as_sql()
  File "/Users/Pat/.virtualenvs/envsp/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 107, in as_sql
    "annotate() + distinct(fields) not implemented.")
NotImplementedError: annotate() + distinct(fields) not implemented.

Anyone know what's going on here? 谁知道这里发生了什么?

The work-around is to use values('distinct_fieldname') because this will make the final SQL statement perform GROUP BY on that field (you can add more than one fieldname), which essentially is the same. 解决方法是使用values('distinct_fieldname')因为这将使最终的SQL语句在该字段上执行GROUP BY (您可以添加多个字段名),这基本上是相同的。

For instance, if you want to know how many articles exist for a given 'filename' you would do this: 例如,如果您想知道给定'filename'存在多少篇文章,您可以这样做:

results = Attachments.objects.filter(currency='current').values('filename').annotate(num_attachments=Count('article_id')).order_by("num_attachments")

I have find another way, how to overcome this - by using a subquery: 我找到了另一种方法,如何克服这个问题 - 使用子查询:

distinct_articles = Attachments.objects.distinct('article_id')
results = Attachments.objects.filter(currency='current').annotate(num_attachments=Count('article_id')).order_by("num_attachments").filter(id__in=distinct_articles)

This get actually evaluated as one database query in Django. 这实际上被评估为Django中的一个数据库查询。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM