我有两个查询,两个查询都给我自己一个正确的结果。
我尝试合并它们,但是结果错误(数字相乘)。
qs2 = Customer.objects.filter(
opportunity__turnover__date__range=[start, end]
).annotate(
month=TruncMonth('opportunity__turnover__date')
).annotate(
turnover=Sum(
"opportunity__turnover__value",
filter=(
Q(opportunity__turnover__type='Project')
)
),
).order_by(
'name','month'
).values('name','month','turnover')
qs = Customer.objects.filter(
project__worklog__day__range=[start, end]
).annotate(
month=TruncMonth('project__worklog__day')
).annotate(
hours=Sum("project__worklog__effort")/60/60,
hoursBilled=Sum(
"project__worklog__effort",
filter=(
Q(project__worklog__account__category='Abrechenbar')
| Q(project__worklog__account__category='Billable')
)
)/60/60,
).order_by(
'name','month'
).values('name','hours','month','hoursBilled')
df = pd.DataFrame(list(qs2)).merge(pd.DataFrame(list(qs)))
目前,我正在将两个结果都转换为Pandas Dataframes并合并它们-可以,但是效果不好,因为我不需要将其作为Dataframe。
相关模型如下:
class Opportunity(models.Model):
id = models.IntegerField(primary_key=True) #CRMID
customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
probability = models.FloatField(null=True, blank=True, default=None)
closeDate = models.DateField(null=True, blank=True, default=None)
duration = models.IntegerField()
value = models.FloatField(null=True, blank=True, default=None)
name = models.CharField(max_length=200, null=False, blank=False)
type = models.CharField(max_length=100, null=True, blank=True)
class Turnover(models.Model):
opportunity = models.ForeignKey(Opportunity, on_delete=models.CASCADE)
type = models.CharField(max_length=100)
date = models.DateField(null=True, blank=True, default=None)
value = models.FloatField(null=True, blank=True, default=None)
class Worklog(models.Model):
worker = models.ForeignKey(Person, on_delete=models.CASCADE)
day = models.DateField(null=True, blank=True, default=None)
effort = models.FloatField() #timeSpentSeconds
account = models.ForeignKey(Account, on_delete=models.CASCADE, null=True, blank=True)
comment = models.TextField(null=True)
project = models.ForeignKey(Project, on_delete=models.CASCADE)
issue = models.CharField(max_length=200)
class Project(models.Model):
key = models.CharField(max_length=200, primary_key=True)
name = models.CharField(max_length=200, null=False, blank=False)
customer = models.ForeignKey(Customer, on_delete=models.CASCADE, null=True) #this has to come via project category description field
class Customer(models.Model):
id = models.IntegerField(primary_key=True) #CRMID
name = models.CharField(max_length=200, null=True, blank=True, default=None)
这是我目前在一个查询集中拥有所有内容的状态:
qs3 = Customer.objects.filter(
Q(project__worklog__day__range=[start, end])
| Q(opportunity__turnover__date__range=[start, end])
).annotate(
month=TruncMonth('project__worklog__day'),
monthOpp=TruncMonth('opportunity__turnover__date')
).filter(
month=F('monthOpp')
).annotate(
turnover=Sum(
"opportunity__turnover__value",
filter=(
Q(opportunity__turnover__type='Project')
)
),
hours=Sum("project__worklog__effort")/60/60,
hoursBilled=Sum(
"project__worklog__effort",
filter=(
Q(project__worklog__account__category='Abrechenbar')
| Q(project__worklog__account__category='Billable')
)
)/60/60,
).order_by(
'name','month'
).values('name','hours','month','hoursBilled','turnover')
我得到以下结果:
hours hoursBilled month name turnover
0 1640.00 1415.00 2019-01-01 Customer Number ONE 5094288.00
1 1581.67 1482.92 2019-02-01 Customer Number ONE 5801496.00
2 1117.50 1042.50 2019-03-01 Customer Number ONE 2226822.72
3 911.67 557.92 2019-04-01 Customer Number ONE 1395000.00
4 20749.22 14487.72 2019-01-01 Customer The Second 128129544.48
5 15762.83 14163.33 2019-02-01 Customer The Second 194805059.94
6 15550.50 12145.00 2019-03-01 Customer The Second 79077900.00
7 525.00 525.00 2019-04-01 Customer The Second 190400.00
但是会期望得到这样的结果:
hours hoursBilled month name turnover
0 328.00 283.00 2019-01-01 Customer Number ONE 33961.92
1 316.33 296.58 2019-02-01 Customer Number ONE 35592.00
2 223.50 208.50 2019-03-01 Customer Number ONE 25020.48
3 182.33 111.58 2019-04-01 Customer Number ONE 15500.00
4 1482.09 1034.84 2019-01-01 Customer The Second 99479.46
5 1125.92 1011.67 2019-02-01 Customer The Second 248793.18
6 1110.75 867.50 2019-03-01 Customer The Second 102300.00
7 37.50 37.50 2019-04-01 Customer The Second 5440.00
面临的挑战是要考虑两个日期:
project__worklog__day
和opportunity__turnover__date
预期结果是所有客户的列表,以及每月相关的工作日志总数和该月的营业额。
理想情况下填写“缺失”月份,因此每个客户都有一月,二月,三月,四月,即使客户在二月和三月都没有营业额或工作日志,但是我目前的查询还没有这样做。
谢谢!
答案 0 :(得分:0)
您可以使用|像这样的运算符:
merged = qs | qs2
如果这不起作用,您可以手动构造它:
merged = []
for obj in qs:
merged.append(obj)
for element in qs2:
merged.append(qs2)
现在您可以遍历
for item in merged:
print(item)
这是一个可以完成所有工作的功能
def merge(list_of_querysets)
return [element for queryset in list_of_querysets for element in queryset]
merged = merge([qs, qs2])