在 Django 中使用 GROUP_CONCAT 和其他注释

Posted

技术标签:

【中文标题】在 Django 中使用 GROUP_CONCAT 和其他注释【英文标题】:Using GROUP_CONCAT with other annotations in Django 【发布时间】:2018-10-07 00:43:28 【问题描述】:

我在返回文章列表时使用了计算赞成/反对票的注释:

queryset = queryset.annotate(
        upvotes_count=models.Sum(
            models.Case(
                models.When(likes__like_state=1, then=1),
                default=0,
                output_field=models.IntegerField()
            )
        )
    ).annotate(
        downvotes_count=models.Sum(
            models.Case(
                models.When(likes__like_state=-1, then=1),
                default=0,
                output_field=models.IntegerField()
            ))
    )

但是每篇文章也有一些类别作为ManyToMany相关字段,我需要以逗号分隔返回这些类别,所以我写了这个函数:

class GroupConcat(models.Aggregate):

    function = 'GROUP_CONCAT'
    template = "%(function)s(%(distinct)s %(expressions)s %(separator)s)"

    def __init__(self, expression, distinct=False, separator=', ', **extra):
        super(GroupConcat, self).__init__(
            expression,
            distinct='DISTINCT' if distinct else '',
            separator="SEPARATOR '%s'" % separator,
            output_field=models.CharField(),
            **extra
        )

并将其添加到我的注释中:

queryset = queryset.annotate(category=GroupConcat('categories__name'))

它工作正常,但 upvotes_countdownvotes_count 发疯了,开始将结果乘以(!)类别数量。

所以问题是:“有没有办法在 Django 中使用 GROUP_CONCAT 而不分解 SUM 注释?”

【问题讨论】:

相关:***.com/a/38017535, ***.com/q/10340684 【参考方案1】:

非常好的解决方案。 但是要使用 group by 字段操作,您应该使用 order_by 语句。 例如:

Store.objects.all().values('value').order_by('value').annotate(stores=GroupConcat('id'))

会生成sql语句

SELECT store.value, GROUP_CONCAT(store.id SEPARATOR ",") AS stores FROM store WHERE store.value > 0 分组 store.value订购store.valueASC

结果是 价值,商店 1“16,27”

没有 order_by 会是这样的:

选择store.value, GROUP_CONCAT(store.id SEPARATOR ",") AS stores FROM store WHERE store.value > 0 GROUP BY store.id 通过store.valueASC 订购

结果是 价值,商店 1 16 2 27

【讨论】:

注意模型类定义中的默认顺序。

以上是关于在 Django 中使用 GROUP_CONCAT 和其他注释的主要内容,如果未能解决你的问题,请参考以下文章

自定义类实现原生SQL的GROUP_CONCAT的功能

Django 10 模型层 model 元信息,对象优化查询,自定义group_concat,基于jq的ajex异步请求

如何在 Rails 中使用 GROUP_CONCAT?

如何在sql server中使用group_concat进行查询[重复]

MySQL中使用group_concat遇到的坑

在 Netezza 中使用 GROUP_CONCAT 时缺少 ORDER BY 的解决方法