首页 > 解决方案 > 使用带注释的字段执行 groupby 计数的问题

问题描述

语境

我有一个名为Article的表/模型。

在这个模型中,我有几个字段,例如到期日期、可见性和状态。这些字段确定是否应显示文章。本质上,所需的逻辑是这样的:

display = True
if status == 'Private'; display = False
if visibility == False; display = False
... 

为了简单起见,在这篇文章中,我将只使用一个字段:status. 该status字段是 a CharField,选择为'Private''Public'

为了制定显示逻辑,我使用注释。这个比较简单:

all_articles = Article.objects.annotate(
    display=Case(When(status='Private', then=Value(False)), default=Value(True), output_field=models.BooleanField())
)

displayed_articles = all_articles.filter(display=True)
notdisplayed_articles = all_articles.filter(display=False)

目标

有了这个设置,我想使用 Django ORM 来执行 group by 计数,以确定有多少文章正在显示,有多少没有。

结果会像这样以 SQL 表格格式显示:

展示 数数
真的 500
错误的 2000

问题

这是实现我的目标的自然方式:

queryset = Article.objects.annotate(
    display=Case(
        When(status='Private', then=Value(False)), default=Value(True), output_field=models.BooleanField()
    )
).values('display').annotate(count=Count('id')).order_by()

print(queryset)

期待

我期待这样的事情:

<QuerySet [{'display': True, 'count': 500}, {'display': False, 'count': 2000}]>

错误

但是,我得到了这个:

django.db.utils.ProgrammingError: ('42000', "[42000] [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Column 'blog_article.status' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause. (8120) (SQLExecDirectW)")

为什么会发生这种情况,我该如何解决?

调查 SQL 查询

我通过以下方式查看了生成的 SQL 查询:

print(queryset.query)
SELECT CASE
        WHEN [blog_article].[status] = Private THEN False
        ELSE True
    END AS [display],
    COUNT_BIG([blog_article].[id]) AS [count]
FROM [blog_article]
GROUP BY CASE
        WHEN [blog_article].[status] = Private THEN False
        ELSE True
    END

查询的一般结构看起来不错,我只需要对其进行一些小改动。以下查询已针对数据库成功执行。

SELECT CASE
        WHEN [faq_faq].[status_type] = 'Private' THEN 0
        ELSE 1
    END AS [display],
    COUNT_BIG([faq_faq].[id]) AS [count]
FROM [faq_faq]
GROUP BY CASE
        WHEN [faq_faq].[status_type] = 'Private' THEN 0
        ELSE 1
    END

我还测试了使用 运行此查询pyodbc,并且已成功执行。

标签: pythonsql-serverdjango

解决方案


推荐阅读