Django 聚合字段,但按日期过滤
Django aggregate field, but filtered by date
我正在尝试注释另一个模型的总和,但按日期过滤了。
我有模型 Employee
和 Shift
,Shift
有一个名为 dur
的 DecimalField,一个 DateTimeField start
和一个外键员工.
class Employee(models.Model):
name = models.CharField(max_length=64)
class Shift(models.Model):
employee = models.ForeignKey(Employee, on_delete=models.CASCADE)
start = models.DateTimeField()
dur = models.DecimalField(max_digits=4, decimal_places=2, default=0)
使用 Employee.objects.all().annotate(Sum('shift__dur'))
我可以添加所有班次的总和,但是 我如何过滤这些班次,例如仅对给定日期范围内的班次求和?
提前致谢!
您可以过滤例如:
Employee.objects.filter(
<strong>shift__start__range=('2022-01-01', '2022-01-31')</strong>
).annotate(
<strong>total=Sum('shift__dur')</strong>
)
这只会显示 2022 年 1 月 的班次。此外,2022 年 1 月 没有任何班次的 Employee
将被过滤掉。
您还可以获得每周的数据,例如:
from django.db.models.functions import TruncWeek
Shift.objects.values(
'employee_id',
<strong>week=TruncWeek('start')</strong>
).annotate(
<strong>total=Sum('dur')</strong>
).order_by('employee_id', 'week')
这将构造一个 QuerySet
具有:
<QuerySet [
{'employee_id': 1, 'week': date(2022, 1, 3), 'total': Decimal('14.25')},
{'employee_id': 1, 'week': date(2022, 1, 10), 'total': Decimal('13.02')},
{'employee_id': 1, 'week': date(2022, 1, 17), 'total': Decimal('17.89')},
{'employee_id': 2, 'week': date(2022, 1, 3), 'total': Decimal('57.3')},
{'employee_id': 2, 'week': date(2022, 1, 17), 'total': Decimal('18.30')}
]>
因此,这使得每个员工的主键和每周(该周被截断为从星期一开始)进行聚合,并且总计列出了 dur
班次的总数。如果对于给定的 employee_id
-week
组合,没有移位,那么这将 not 出现在查询集中。因此,如果您想在这几周内引入零,则需要做一些 post-processing。
我正在尝试注释另一个模型的总和,但按日期过滤了。
我有模型 Employee
和 Shift
,Shift
有一个名为 dur
的 DecimalField,一个 DateTimeField start
和一个外键员工.
class Employee(models.Model):
name = models.CharField(max_length=64)
class Shift(models.Model):
employee = models.ForeignKey(Employee, on_delete=models.CASCADE)
start = models.DateTimeField()
dur = models.DecimalField(max_digits=4, decimal_places=2, default=0)
使用 Employee.objects.all().annotate(Sum('shift__dur'))
我可以添加所有班次的总和,但是 我如何过滤这些班次,例如仅对给定日期范围内的班次求和?
提前致谢!
您可以过滤例如:
Employee.objects.filter(
<strong>shift__start__range=('2022-01-01', '2022-01-31')</strong>
).annotate(
<strong>total=Sum('shift__dur')</strong>
)
这只会显示 2022 年 1 月 的班次。此外,2022 年 1 月 没有任何班次的 Employee
将被过滤掉。
您还可以获得每周的数据,例如:
from django.db.models.functions import TruncWeek
Shift.objects.values(
'employee_id',
<strong>week=TruncWeek('start')</strong>
).annotate(
<strong>total=Sum('dur')</strong>
).order_by('employee_id', 'week')
这将构造一个 QuerySet
具有:
<QuerySet [
{'employee_id': 1, 'week': date(2022, 1, 3), 'total': Decimal('14.25')},
{'employee_id': 1, 'week': date(2022, 1, 10), 'total': Decimal('13.02')},
{'employee_id': 1, 'week': date(2022, 1, 17), 'total': Decimal('17.89')},
{'employee_id': 2, 'week': date(2022, 1, 3), 'total': Decimal('57.3')},
{'employee_id': 2, 'week': date(2022, 1, 17), 'total': Decimal('18.30')}
]>
因此,这使得每个员工的主键和每周(该周被截断为从星期一开始)进行聚合,并且总计列出了 dur
班次的总数。如果对于给定的 employee_id
-week
组合,没有移位,那么这将 not 出现在查询集中。因此,如果您想在这几周内引入零,则需要做一些 post-processing。