Django:如何基于它覆盖字段';聚合查询中的s值(在多个列上联接)
我已经在互联网的不同角落和Django项目文档上寻找了一段时间,但没有成功,因此我的问题是: 作为后台,我正在用一个外部API同步模型,所以我不希望改变模型结构 我有以下模型(为了简洁起见,只留下相关字段):Django:如何基于它覆盖字段';聚合查询中的s值(在多个列上联接),django,postgresql,django-orm,Django,Postgresql,Django Orm,我已经在互联网的不同角落和Django项目文档上寻找了一段时间,但没有成功,因此我的问题是: 作为后台,我正在用一个外部API同步模型,所以我不希望改变模型结构 我有以下模型(为了简洁起见,只留下相关字段): 时间输入: 类时间条目(models.Model): id=CharField(主键=True,最大长度=255) 持续时间\u DecimalField=DecimalField(最大数字=5,小数位数=2,详细名称=dec duration') start=DateTimeField
- 时间输入:
类时间条目(models.Model): id=CharField(主键=True,最大长度=255) 持续时间\u DecimalField=DecimalField(最大数字=5,小数位数=2,详细名称=dec duration') start=DateTimeField() project=ForeignKey(project,models.SET_NULL,blank=True,NULL=True) user=ForeignKey(user,models.SET_NULL,blank=True,NULL=True)
- 会员资格
类成员资格(models.Model): user=ForeignKey(user,models.SET_NULL,blank=True,NULL=True) project=ForeignKey(project,models.SET_NULL,blank=True,NULL=True) 小时费率=外键(HourlyRate,models.SET\u NULL,blank=True,NULL=True) 活动=布尔字段(默认值=真)
- 使用者
类用户(models.Model): 小时费率=小数字段(最大位数=7,小数位数=2,空白=True,空=True)
- 钟楼
class HourlyRate(models.Model): 金额=货币字段(最大数字=10,小数位数=2,空白=True,空=True,默认货币=USD)
- 用户级查询
TimeEntry.objects.filter(项目id='xxxxxx') .annotate(年=提取年('start'),月=提取月('start'))\ .值('年'、'月')\ .annotate(sum=ExpressionWrapper(sum(F('user\u hourly\u rate'))*F('duration\u DecimalField'))、DecimalField()、hours\u sum=sum('duration\u decimal')、count=count('id'))\ .值('year'、'month'、'count'、'sum')。排序依据('year'、'month')
- 输出:
+----------------------------------------------+ | Results | +----+------+-------+------+-----------+-------+ | No | year | month | sum | hours_sum | count | +----+------+-------+------+-----------+-------+ | 1 | 2020 | 1 | 1000 | 95 | 15 | +----+------+-------+------+-----------+-------+ | 2 | 2019 | 12 | 990 | 87 | 9 | +----+------+-------+------+-----------+-------+ | 3 | 2019 | 11 | 1250 | 113 | 21 | +----+------+-------+------+-----------+-------+ | | ... | | | | | +----+------+-------+------+-----------+-------+
- 成员级别查询
TimeEntry.objects.filter(项目id='xxxxxx') .annotate(年=提取年('start'),月=提取月('start'))\ .值('年'、'月')\ .annotate(sum=ExpressionWrapper(sum(F('project\u membership\u hourly\u rate\u amount'))*F('duration\u DecimalField'))、DecimalField()、count=count('id'))\ .order_by('-year','-month')。值('year','month','count','sum'))
- 成员级别生成SQL
选择提取(“时间输入”中的“年”。“欧洲/苏黎世”时区的“开始”)作为“年”, 将“时间输入”中的“月”、“时区“欧洲/苏黎世”中的“开始”提取为“月”, 总和((“hourlyrate”,“amount”*“timeentry”,“duration\u decimal”))作为“总和”, 计数(“时间项”。“id”)为“计数” 从“时间输入” “时间项”“项目id”“项目”“id”上的内部联接“项目” “项目”“id”“clockify_会员”“项目id”上的左侧外部加入“会员资格” 左外联接“hourlyrate”ON(“会员”,“小时费率”\u id“=“hourlyrate”,“id”) 其中“时间项”。“项目id”=“xxxxxx” 按摘录分组(“年”来自“时间输入”,“开始”来自“欧洲/苏黎世”时区),摘录(“月”来自“时间输入”,“开始”来自“欧洲/苏黎世”时区) 按“年”说明、“月”说明订购
- 成员级别生成SQL[已更正]
选择提取(“时间输入”中的“年”。“欧洲/苏黎世”时区的“开始”)作为“年”, 将“时间输入”中的“月”、“时区“欧洲/苏黎世”中的“开始”提取为“月”, 总和((“hourlyrate”,“amount”*“timeentry”,“duration\u decimal”))作为“总和”, 计数(“时间项”。“id”)为“计数” 从“时间输入” --开始>这里是合并前两个分离联接的两列上的联接 左外部加入“成员资格”在(“时间项”。“用户id”=“成员资格”。“用户id”和“成员资格”。“项目id”=“时间项”。“项目id”)
--我建议您在
模型上定义一个指向TimeEntry
成员身份的
外来对象 来自django.db.models.fields.related导入外来对象的
类时间条目(models.Model): ... project=ForeignKey(project,models.SET_NULL,blank=True,NULL=True) user=ForeignKey(user,models.SET_NULL,blank=True,NULL=True) 成员资格=外国对象( 会员 from_fields=('project','user'), to_字段=(“项目”、“用户”) )
定义了此关系后,您的查询集将能够使用
我建议您在Coalesce('membership\uu hourly\u rate'、'membership\uu user\uu hourly\u rate')
模型上定义一个指向TimeEntry
成员身份的
外来对象 来自django.db.models.fields.related导入外来对象的
类时间条目(models.Model): ... project=ForeignKey(project,models.SET_NULL,blank=True,NULL=True) user=ForeignKey(user,models.SET_NULL,blank=True,NULL=True) 成员资格=外国对象( 会员 from_fields=('project','user'), to_字段=(“项目”,