如何用单条Django查询按月份汇总指定条件的valor_da_operacao?
Django查询实现按月份分组汇总股息数据
问题描述
我的Movimentacao模型定义如下:
class Movimentacao(models.Model): entrada_saida = models.CharField(max_length=100) date = models.DateField() movimentacao = models.CharField(max_length=200) produto = models.CharField(max_length=300) instituicao = models.CharField(max_length=200) quantidade = models.IntegerField() preco_unitario = models.DecimalField(max_digits=19, decimal_places=2) valor_da_operacao = models.DecimalField(max_digits=19, decimal_places=2)
我需要筛选出produto字段等于"dividendo"的数据,按date字段的月份分组,汇总每个月的valor_da_operacao字段值,最终要得到这样的格式:
{"dict": [["2022-Jan", 1.530], ["2022-Feb", 422], ["2022-Mar", 1.822]]}
请问怎么用单条Django查询实现这个需求?
解决方案
你可以通过Django ORM结合数据库函数来实现,以下是具体代码:
通用兼容版本(适配多数据库)
首先导入需要的模块:
from django.db.models import Sum from django.db.models.functions import ExtractYear, ExtractMonth from django.utils.dateformat import DateFormat
然后编写查询并转换格式:
# 执行分组汇总查询 query_results = Movimentacao.objects.filter(produto='dividendo') \ .annotate( year=ExtractYear('date'), month=ExtractMonth('date') ) \ .values('year', 'month') \ .annotate(total_valor=Sum('valor_da_operacao')) \ .order_by('year', 'month') # 转换为目标格式 final_result = { "dict": [ [f"{item['year']}-{DateFormat(item['month']).format('M')}", float(item['total_valor'])] for item in query_results ] }
PostgreSQL专属优化版本
如果你的项目用的是PostgreSQL数据库,可以直接在查询中生成YYYY-Mon格式的日期字符串,减少后续格式转换步骤:
from django.db.models import Sum, Value from django.db.models.functions import ExtractYear, Concat, ToChar # 直接生成日期格式并分组汇总 query_results = Movimentacao.objects.filter(produto='dividendo') \ .annotate( year_month=Concat( ExtractYear('date'), Value('-'), ToChar('date', 'Mon') ) ) \ .values('year_month') \ .annotate(total_valor=Sum('valor_da_operacao')) \ .order_by('year_month') # 转换为目标格式 final_result = { "dict": [[item['year_month'], float(item['total_valor'])] for item in query_results] }
代码说明
filter(produto='dividendo'):精准筛选出产品为股息的记录annotate(year=ExtractYear('date'), month=ExtractMonth('date')):从date字段中提取年份和月份,用于后续分组values('year', 'month'):指定按年份和月份进行分组annotate(total_valor=Sum('valor_da_operacao')):对每个分组的valor_da_operacao字段求和- 最后通过列表推导式将查询结果转换为你需要的格式,同时把Decimal类型的求和结果转为float,年份和月份拼接成
YYYY-Mon的形式
内容的提问来源于stack exchange,提问作者Felipe Dourado
相关产品推荐
相关产品推荐

