【发布时间】:2021-07-27 16:30:13
【问题描述】:
问题
假设我有一个名为 Price 的表,它是一个带有时间戳、值和前一天差异的时间序列。为了简化表格,我只放了日期而不是小时、分钟等:
| timestamp | value | difference |
|---|---|---|
| 2021-01-21 | 500 | 500 |
| 2021-01-22 | 1000 | 500 |
| 2021-01-23 | 1500 | 500 |
| 2021-01-24 | 2000 | 500 |
| 2021-01-25 | 2500 | 500 |
这些值可能不正确,用户可以随时使用名为 CorrectedPrice 的第二个表进行更正。用户甚至可以在第一个价格值的日期之前更正起始值:
| timestamp | value |
|---|---|
| 2021-01-15 | 1000 |
| 2021-01-23 | 500 |
通过合并这两个信息,日期 2021-01-21 和 2021-01-26 之间生成的查询集应该是:
| timestamp | value |
|---|---|
| 2021-01-21 | 1500 |
| 2021-01-22 | 2000 |
| 2021-01-23 | 1000 |
| 2021-01-24 | 1500 |
| 2021-01-25 | 2000 |
Django 模型
我们有一个Stock模型:
class Stock(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.Charfield(unique=True)
价格模型:
class Price(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
value = models.IntegerField()
difference = models.IntegerField() # done with a signal on pre_save
timestamp = AutoCreatedField()
stock = models.ForeignKey(Stock, on_delete=models.CASCADE)
然后我们有 CorrectedPrice 模型:
class CorrectedPrice(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
value = models.IntegerField()
timestamp = AutoCreatedField()
stock = models.ForeignKey(Stock, on_delete=models.CASCADE)
我尝试了什么
start_date = ... # 2021-01-21
end_date = ... # 2021-01-26
Price.objects.filter(
name=stock_name,
timestamp__range(start_date, end_date)
).annotate(
value=Window(Sum("difference"), order_by=F("timestamp").asc()),
timestamp=F("timestamp")
)
这基本上没有考虑到 CorrectedPrice 表。我设法在value=Window(Sum("difference"), order_by=F("timestamp").asc()) 之后添加了一个常量,例如value=Window(Sum("difference"), order_by=F("timestamp").asc()) + 1,但这只会考虑一个值。
如何解决这个问题,并在第三张表中显示结果? Django ORM 是否能够以适当的方式做到这一点?
【问题讨论】:
-
如果已经存储为列,为什么还要使用差的总和来计算值?实际上,如果您尝试添加与现有字段同名的注解,ORM 将引发您的注解与模型上的字段冲突的异常。
-
我认为使用差异可能更容易进行查询。如果用户将修正后的价格设置为 100,如果差值为 200,那么我们知道我们必须添加 100+200。而不是在查询本身中回顾前一天价格的价值。您提出什么替代解决方案?
-
首先,存储值和差异是多余的。一个总是可以从另一个计算出来的。我的偏好是存储该值并在需要时计算差异,但您的应用程序可能会考虑使存储差异更好。其次,我不明白您为什么要使用差异来计算价值。如果用户更正价格,是否应该影响所有后续价格?
-
是的,它应该会影响所有后续价格,但计算可能会很密集,因此需要工作人员才能完成,直到最新数据。此外,当工作人员已经在运行时,用户可能会更改价格,这会增加额外的复杂性。保留原始股票价格信息对于其他用例至关重要。合并更正价格和原始价格是一项关键功能,但每 x 个月使用一次。大多数用户只想查看 7 天日期范围内的第 3 个表格。
标签: python sql django django-orm