在正常情况下,使用带有参数的StringAggdistinct=True
是有效的,例如:
entities = entities.annotate(roles=StringAgg(
"credits__role__name",
delimiter=", ",
distinct=True,
ordering="credits__role__name"
))
但是当与条件一起使用时expression
,它会引发异常django.db.utils.ProgrammingError: in an aggregate with DISTINCT, ORDER BY expressions must appear in argument list
,例如:
releases = releases.annotate(credits_primary=StringAgg(
Case(When(credits__type="primary", then="credits__entity__name")),
delimiter=", ",
distinct=True,
ordering="credits__entity__name"
))
为什么会这样?有没有办法使第二个例子起作用?
编辑:这是我目前正在使用的完整代码示例,可以正常工作。我想要做的是entity
从聚合列表字符串中消除重复的 s。
if request.GET.get("order[0][name]"):
order = request.GET["order[0][name]"]
if order == "credits_primary":
releases = releases.annotate(credits_primary=StringAgg(
Case(When(credits__type="primary", then="credits__entity__name")),
delimiter=", ",
ordering="credits__entity__name"
))
elif order == "credits_secondary":
releases = releases.annotate(credits_secondary=StringAgg(
Case(When(credits__type="secondary", then="credits__entity__name")),
delimiter=", ",
ordering="credits__entity__name"
))
else:
order = "title"
# Order releases
if request.GET.get("order[0][dir]") == "desc":
releases = releases.order_by(F(order).desc(nulls_last=True), "title")
else:
releases = releases.order_by(F(order).asc(nulls_last=True), "title")
请注意,arelease
可能没有任何主要或次要学分,并且 1entity
可能拥有相同的多个主要或次要学分release
(具有不同的role
s)。
尝试以下查询,它应该给出预期的结果:
filter
您应该在 内部使用StringAgg
,我在 的文档中没有找到这样的示例,但您可以通过查看签名在此处StringAgg
看到它。在此页面上,您可以看到 聚合函数中的 的使用。filter
Count
编辑:请参阅此答案以获得更优美且更易读的解决方案。
出于我完全不明白的原因,
credits__entity__name
即使ordering="credits__entity__name"
省略了,它似乎也会按排序。也许默认情况下它按字母顺序排序,或者按在条件中传递值的字段排序expression
。Django 文档未指定默认行为。(请注意,Credit
模型的默认排序不是按实体排序)换句话说,这会产生所需的结果:
希望对 Django 和/或 PostgreSQL 有更深入了解的人能够给出答案来解释为什么会出现这种情况。
发生该错误的原因是 PostgreSQL 要求
ORDER BY
列出现在 中DISTINCT
。确保
ORDER BY
表达式和DISTINCT
参数都对齐。您可以Filter
在聚合之前使用预过滤,如下所示:替代方案:使用
Filter
而不是Case
如果您的Case
表达式充当filter
,另一种方法是在聚合中直接使用过滤器:告诉我是否有帮助。