[英]Django annotate + SUM how to get all entries
我的模型
class Machine(models.Model):
machineName = models.CharField(verbose_name="Machine Name", max_length=20, blank=False, null=False)
class SalesReport(models.Model):
machine = models.ForeignKey(Machine, on_delete=models.CASCADE, null=False, blank=False)
deviceDate = models.CharField(max_length=200, null=True, blank=True)
serverDate = models.DateTimeField(auto_now_add=True)
totalPrice = models.FloatField()
我有 3 台機器,我想獲得過去 7 天每台機器的總銷售額。
我的查詢是
from django.db.models import Sum, Value as V
from django.db.models.functions import Coalesce
SalesReport.objects.values("serverDate__date", "machine__machineName").annotate(
... sales=Coalesce(Sum("totalPrice"),V(0))).filter(
... serverDate__gte=week_start,
... serverDate__lte=week_end)
這給出了以下結果,
[{'serverDate__date': datetime.date(2020, 7, 22), 'machine__machineName': 'machine__1', 'sales': 15.0},
{'serverDate__date': datetime.date(2020, 7, 28), 'machine__machineName': 'machine__1', 'sales': 145.0},
{'serverDate__date': datetime.date(2020, 7, 28), 'machine__machineName': 'machine__2', 'sales': 270.0},
{'serverDate__date': datetime.date(2020, 7, 28), 'machine__machineName': 'machine__3', 'sales': 255.0}]
我想要得到的是
[{'serverDate__date': datetime.date(2020, 7, 22), 'machine__machineName': 'machine__1', 'sales': 15.0},
{'serverDate__date': datetime.date(2020, 7, 22), 'machine__machineName': 'machine__2', 'sales': 0.0},
{'serverDate__date': datetime.date(2020, 7, 22), 'machine__machineName': 'machine__3', 'sales': 0.0},
{'serverDate__date': datetime.date(2020, 7, 28), 'machine__machineName': 'machine__1', 'sales': 145.0},
{'serverDate__date': datetime.date(2020, 7, 28), 'machine__machineName': 'machine__2', 'sales': 270.0},
{'serverDate__date': datetime.date(2020, 7, 28), 'machine__machineName': 'machine__3', 'sales': 255.0}]
我正在嘗試用 Coalesce 來做這件事,但我弄錯了。
*我使用 mysql 作為數據庫。 一個數據庫特定的查詢也很好。
問題是您在某些日期沒有任何銷售。 它比 django ORM 更像是一個 DB 特定問題。 我建議在您的機器表上使用帶有左外連接的原始 sql => 取出所有機器並在存在時列出銷售。
machine = Machine.objects.raw('''
SELECT machine.id, machine.name, sales.sid FROM app_machinelist as machine
LEFT JOIN (select sales_id as sid
from app_sales
where profile_id = {0}) sales
ON sales.sid = machine.id
ORDER BY machine.name ASC
'''.format(myuser.id))
此示例有效,但出於安全原因,最好通過字典傳遞參數
machine = Machine.objects.raw(mysql, params)
在哪里
params = {'profile_id': pk, 'startdate': startdate, 'enddate': enddate}
mysql = '''
SELECT machine.id, machine.name, sales.sid FROM app_machinelist as machine
LEFT JOIN (select sales_id as sid
from app_sales
where profile_id = %(profile_id)s) sales
ON sales.sid = machine.id
ORDER BY machine.name ASC
'''
由於它是更多 SQL 問題,因此我添加了更具體的答案
SELECT m.machineName, s.price
FROM machine m LEFT OUTER JOIN (
SELECT machine_id id, sum(totalPrice) price
FROM salesreport
WHERE serverDate BETWEEN DATE_SUB(curdate(), INTERVAL 1 WEEK) and curdate()
GROUP BY by machine_id) s on m.id = s.id
如果您希望 serverDate 作為輸出,您必須應用聚合 function (Max, Min),因為它位於您的 SalesReport 表中。
這取決於 serverDate 代表什么。 如果是您購買機器的日期,那么它應該在機器表中,並且可以直接從機器表中選擇(並且WHERE BETWEEN子句必須存在子選擇並且也適用於機器表)。 如果它是 salesDate,那么它必須在 SalesReport 中,並且您必須在其上應用聚合 function。 即:你可以在一周內有 7 次約會......
SELECT m.machineName, s.MaxserverDate, s.price
FROM machine m LEFT OUTER JOIN (
SELECT machine_id id, max(serverDate) MaxserverDate, sum(totalPrice) price
FROM salesreport
WHERE serverDate BETWEEN DATE_SUB(curdate(), INTERVAL 1 WEEK) and curdate()
GROUP BY by machine_id) s on m.id = s.id
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.