Django ORM获取字段的最大值和相应的其他列值

abc*_*123 5 python django pandas

我有一个数据框:

`exp_no`   'time'   'price'
Run Code Online (Sandbox Code Playgroud)
  1       0:00:00     20.0
  1       7 days      45.0
  1       15 days     100.0
  2       0:00:00     20.0
  2       7 days      45.0
  2       15 days     100.0
Run Code Online (Sandbox Code Playgroud)

对应的Django模型:

class StData(models.Model):
      exp_no = models.ForeignKey(StIndex, on_delete=models.CASCADE)
      time = models.DateTimeField()
      price = models.DecimalField(max_digits=10, decimal_places=2)   
Run Code Online (Sandbox Code Playgroud)

我想制作一个较小的表,其中包含 exp_no、max_time 和相应的价格,如下所示:

 `exp_no`   'time'   'price'
Run Code Online (Sandbox Code Playgroud)
  1       15 days     100.0
  2       15 days     100.0
Run Code Online (Sandbox Code Playgroud)

在 pandas 中,我会df.groupby('exp_no')['time', 'price'].max().reset_index() 做得到想要的表。

在 Django ORM 注释中,如果我这样做,可以获得相同的结果(或查询集):

qs.values('exp_no').annotate(max_time=Max('time')).order_by()
Run Code Online (Sandbox Code Playgroud)

它给了我exp_no和时间,但我也想得到相应的价格。我已经在SO中查看了这个答案:Django orm getlatest for every group

但不知道如何得到价格。将 Django 2.0 与 sqlite3 结合使用。

我很感激任何帮助。

Wil*_*sem 5

您的问题归结为获取StData具有最大列的记录的对象(或值)time。所以我们不需要聚合,而是获取相对于time列的最小或最大行。

获取StData最大的对象time

您可以last()在订购时获取该行'time',例如:

stdata_max_time = qs.order_by('time').last()  # will return a StData
Run Code Online (Sandbox Code Playgroud)

或者:

stdata_max_time = qs.order_by('-time').first()  # will return a StData
Run Code Online (Sandbox Code Playgroud)

如果是 NULLable(不在此处),您可以通过指定在排序时应将这些元素分别放置为第一个/最后一个元素来time确保您不会检索行:NULL

from django.db.models import F

# two alternatives
stdata_max_time = qs.order_by(F('time', nulls_first=True)).last()
stdata_max_time = qs.order_by(F('-time', nulls_last=True)).first()
Run Code Online (Sandbox Code Playgroud)

因此,这是一个StData对象,因此您可以从该对象中检索所需的所有相关信息。由于它是一个StData对象,它的行为也会像这样(因此您定义的额外属性、方法等也将起作用)。

获取最大值的值time

这完全相似,只是我们.values(..)在查询中放置了一个调用:

stdata_max_time = qs.order_by('time').values('exp_no', 'time', 'price').last()
Run Code Online (Sandbox Code Playgroud)

但除非有一些非常好的理由,否则我个人更喜欢获取该StData对象,因为这意味着“包含电池”(您将获得在该对象的类中编写的所有逻辑StData)。