如何在Django ORM中按条件分组和汇总条件

时间:2019-04-25 12:53:51

标签: django django-orm

我有一个Django查询,以获取每位员工每天的平均工作时间(每天可能有多个工作日志)。我想将这些分配给工作日和周末。

这是工作日志模型:

class Worklog(models.Model):
    worker = models.ForeignKey(Person, on_delete=models.CASCADE)
    day = models.DateField(null=False, blank=False)
    effort = models.FloatField()
    comment = models.TextField(null=True)
    project = models.ForeignKey(Project, on_delete=models.CASCADE)

我尝试了以下方法:

    qs = Worklog.objects.filter(
                day__range=[start,end]
            ).values(
                'worker__fullname'

            ).annotate(
                weekday=Case(
                    When(Q(day__week_day=1) | Q(day__week_day=7), then=1),
                    default=0,
                    output_field=IntegerField(),
                )
            ).values(
                'worker__fullname'
            ).annotate(
                weekdayAvg=Case(
                    When(Q(weekday=0), then=Cast(
                    Sum('effort')/Count('day', distinct=True)/60/60, FloatField()
                )),
                    default=0,
                    output_field=FloatField(),
                ),
                weekendAvg=Case(
                    When(Q(weekday=1), then=Cast(
                    Sum('effort')/Count('day', distinct=True)/60/60, FloatField()
                )),
                    default=0,
                    output_field=FloatField(),
                )
            ).order_by('worker__fullname')

这给了我结果

     weekdayAvg  weekendAvg                        worker__fullname
0      9.125000        0.00                        Klaus
1      0.000000       11.00                        Klaus
2      6.977273        0.00                        Peter
3      7.827586        0.00                        Carl
4      0.000000       13.00                        Carl
5      8.169643        0.00                        Chris
6      0.000000        2.25                        Chris

但是,预期结果将更像:

     weekdayAvg  weekendAvg                        worker__fullname
0      9.125000        11.00                       Klaus
1      6.977273        0.00                        Peter
2      7.827586        13.00                       Carl
3      8.169643        2.25                        Chris

任何想法如何实现这一目标?

我也对查询的简化感到高兴。 谢谢!

1 个答案:

答案 0 :(得分:0)

我设法自己得到它。我以前不了解的功能是在聚合函数(OpenSharedResourceID3D11Texture2D等)中使用filter=参数

Sum

我还添加了Count,否则总和将返回 qs = Worklog.objects.filter( day__range=[start,end] ).values( 'worker__fullname' ).annotate( weekdayAvg=Cast(Coalesce(Sum('effort', filter=(~Q(day__week_day=1) & ~Q(day__week_day=7)))/Count('day', distinct=True, filter=(~Q(day__week_day=1) & ~Q(day__week_day=7)))/60/60, 0), FloatField()), weekdayCnt=Cast(Coalesce(Count('day', distinct=True, filter=(~Q(day__week_day=1) & ~Q(day__week_day=7))), 0), FloatField()), weekendAvg=Cast(Coalesce(Sum('effort', filter=(Q(day__week_day=1) | Q(day__week_day=7)))/Count('day', distinct=True, filter=(Q(day__week_day=1) | Q(day__week_day=7)))/60/60, 0), FloatField()), weekendCnt=Cast(Coalesce(Count('day', distinct=True, filter=(Q(day__week_day=1) | Q(day__week_day=7))), 0), FloatField()), ).order_by('weekdayAvg', 'worker__fullname') (根据this帖子)