DJANGO中实现GROUP_CONCAT方法,分组聚合

问题:
Say I have the following table called fruits:

idtypename
0applefuji
1applemac
2orangenavel

My goal is to ultimately come up with a count of the different types and a comma-delimited list of the names:

apple, 2, "fuji,mac"
orange, 1, "navel"

This can be easily done with GROUP_CONCAT in MySQL but I’m having trouble with the Django equivalent. This is what I have so far but I am missing the GROUP_CONCAT stuff:

query_set = Fruits.objects.values(‘type’).annotate(count=Count(‘type’)).order_by(’-count’)
I would like to avoid using raw SQL queries if possible.

Any help would be greatly appreciated!

回答:

NOTICE that Django (>=1.8) provides Database functions support. https://docs.djangoproject.com/en/dev/ref/models/database-functions/#concat

from django.db.models import Aggregate, CharField

class GroupConcat(Aggregate):
    function = 'GROUP_CONCAT'
    template = '%(function)s(%(distinct)s%(expressions)s%(ordering)s%(separator)s)'

    def __init__(self, expression, distinct=False, ordering=None, separator=',', **extra):
        super(GroupConcat, self).__init__(
            expression,
            distinct='DISTINCT ' if distinct else '',
            ordering=' ORDER BY %s' % ordering if ordering is not None else '',
            separator=' SEPARATOR "%s"' % separator,
            output_field=CharField(),
            **extra
        )

Usage:

LogModel.objects.values('level', 'info').annotate(
    count=Count(1), time=GroupConcat('time', ordering='time DESC', separator=' | ')
).order_by('-time', '-count')

我的项目里的应用举例

from data_assets.utils.models import GroupConcat
from django.db.models.functions import Substr, StrIndex
from django.db.models import CharField
from .models import DataFlowField

fields = DataFlowField.objects.filter(table__database__business_type=3).filter(
    Q(provide_department='') | Q(provide_department__isnull=True))
# for f in fields: # 优化 for-save有点慢
#     f.provide_department = f.create_department.split(',')[0] if f.create_department else '未知部门'
#     f.save(update_fields=['provide_department'])
# 改用StrIndex和Substr切分字符串,批量更新
fields.filter(create_department__contains=',').annotate(
    smith_index=StrIndex(F('create_department'), Value(','))).annotate(
    dept1=Substr(F('create_department'), 1, F('smith_index')-1,  output_field=CharField())).update(
    provide_department=F('dept1'))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值