Django annotate + SUM如何获取所有条目
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 问题相比,它更像是一个特定于数据库的问题。我建议在您的机器上使用 raw sql 和左外连接 table => 获取所有机器并列出销售情况。
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 作为输出,您必须应用聚合函数(最大值、最小值),因为它位于您的销售报表中 table。
这取决于 serverDate 代表什么。如果它是你购买机器的日期那么它应该在机器 table 并且它可以直接从机器 table 编辑 select (并且 WHERE BETWEEN 子句必须存在于子 - select 也适用于机器 table)。如果它是 salesDate,那么它必须在 SalesReport 中,并且您必须对其应用聚合函数。即:您一周内可能有 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
我的模型
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 问题相比,它更像是一个特定于数据库的问题。我建议在您的机器上使用 raw sql 和左外连接 table => 获取所有机器并列出销售情况。
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 作为输出,您必须应用聚合函数(最大值、最小值),因为它位于您的销售报表中 table。
这取决于 serverDate 代表什么。如果它是你购买机器的日期那么它应该在机器 table 并且它可以直接从机器 table 编辑 select (并且 WHERE BETWEEN 子句必须存在于子 - select 也适用于机器 table)。如果它是 salesDate,那么它必须在 SalesReport 中,并且您必须对其应用聚合函数。即:您一周内可能有 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