【问题标题】:Django filter by Count annotated inside SubqueryDjango按子查询中注释的计数过滤
【发布时间】:2019-06-06 19:50:19
【问题描述】:

这是一个抽象和简化的例子。

假设我想获取作者并在类别中注释最少数量的书籍(如果它大于三)。

Book 和 Author 模型并没有与 ForeignKey 字段连接(记住,抽象和简化,这是有原因的):

Author(models.Model):
    name = models.CharField(max_length=250)

Book(models.Model):
    author_name = models.CharField(max_length=250)
    book_category = models.CharField(max_length=250)

这是我可以重现的最简单的查询:

(Author.objects
 .annotate(min_valuable_count=Subquery(
    Book.objects
        .filter(author_name=OuterRef('name'))
        .annotate(cnt=Count('book_category'))
        .filter(cnt__gt=3)
        .order_by('cnt')
        .values('cnt')[:1],
    output_field=models.IntegerField()
 ))
)

我得到一个错误:

psycopg2.ProgrammingError: missing FROM-clause entry for table "U0"
LINE 1: ... "core_author" GROUP BY "core_author"."id", "U0"."id" ...
                                                       ^

这里是 SQL:

SELECT "core_author"."id", "core_author"."name", (
    SELECT COUNT(U0."book_category") AS "cnt" 
    FROM "core_book" U0 WHERE U0."id" = ("core_author"."chat_id") 
    GROUP BY U0."id" HAVING COUNT(U0."book_category") > 3 
    ORDER BY "cnt" ASC  LIMIT 1) 
AS "min_valuable_count" 
FROM "core_author" 
GROUP BY "core_author"."id", "U0"."id"

更新 #1

我发现删除.filter(cnt__gt=3) 会删除最后一个无法访问U0GROUP BY

SELECT "core_author"."id", "core_author"."name", (
    SELECT COUNT(U0."book_category") AS "cnt" 
    FROM "core_book" U0 WHERE U0."id" = ("core_author"."chat_id") 
    GROUP BY U0."id"
    ORDER BY "cnt" ASC  LIMIT 1) 
AS "min_valuable_count" 
FROM "core_author" 

有什么方法可以在外部查询中删除GROUP BY,而不在子查询中删除.filter(cnt__gt=3)

【问题讨论】:

    标签: django postgresql orm


    【解决方案1】:

    这是一个错误,它将在 django 版本 2.1.6 中修复。这是现在的工作:

    min_valuable_count_qs = Subquery(
        Book.objects
            .filter(author_name=OuterRef('name'))
            .annotate(cnt=Count('book_category'))
            .filter(cnt__gt=3)
            .order_by('cnt')
            .values('cnt')[:1],
        output_field=models.IntegerField()
    )
    
    min_valuable_count_qs.contains_aggregate = False
    
    qs = Author.objects.annotate(min_valuable_count=min_valuable_count_qs))
    

    【讨论】:

      猜你喜欢
      • 2021-07-05
      • 1970-01-01
      • 2011-03-31
      • 2012-03-07
      • 2015-11-15
      • 1970-01-01
      • 2019-12-07
      • 2022-01-19
      • 1970-01-01
      相关资源
      最近更新 更多