Django ORM:根据列的最大值获取行

发布于 2024-08-04 23:45:08 字数 1153 浏览 9 评论 0原文

我有一个 Marketorders 类,其中包含有关单一市场订单的信息,它们收集在市场快照中(由 Snapshot 类表示)。每个订单可以出现在多个快照中,当然最新行是相关的。

class Marketorders(models.Model):
    id = models.AutoField(primary_key=True)
    snapid = models.IntegerField()
    orderid = models.IntegerField()
    reportedtime = models.DateTimeField(null=True, blank=True)
    ...


class Snapshot(models.Model):
    id = models.IntegerField(primary_key=True)
    ...

我正在做的是获取多个快照中的所有订单进行处理,但我只想包含每个订单的最新行。在 SQL 中,我会简单地执行:

SELECT m1.* FROM marketorders m1 WHERE reportedtime = (SELECT max(reportedtime)  
FROM marketorders m2 WHERE m2.orderid=m1.orderid);

或者更好的是使用 join:

SELECT m1.* FROM marketorders m1 LEFT JOIN marketorders m2 ON 
m1.orderid=m2.orderid AND m1.reportedtime < m2.reportedtime 
WHERE m2.orderid IS NULL;

但是,我只是不知道如何使用 Django ORM 来执行此操作。有什么方法可以在不使用原始 SQL 的情况下完成此任务吗?

编辑:只是为了澄清问题。假设我们有以下市价订单(忽略所有不重要的内容并仅使用 orderid、reportedtime):

1, 09:00:00
1, 10:00:00
1, 12:00:00
2, 09:00:00
2, 10:00:00

如何使用 ORM 获取以下集合?

1, 12:00:00
2, 10:00:00

I have a class Marketorders which contains information about single market orders and they are gathered in snapshots of the market (represented by class Snapshot). Each order can appear in more than one snapshot with the latest row of course being the relevant one.

class Marketorders(models.Model):
    id = models.AutoField(primary_key=True)
    snapid = models.IntegerField()
    orderid = models.IntegerField()
    reportedtime = models.DateTimeField(null=True, blank=True)
    ...


class Snapshot(models.Model):
    id = models.IntegerField(primary_key=True)
    ...

What I'm doing is getting all of the orders across several snapshots for processing, but I want to include only the most recent row for each order. In SQL I would simply do:

SELECT m1.* FROM marketorders m1 WHERE reportedtime = (SELECT max(reportedtime)  
FROM marketorders m2 WHERE m2.orderid=m1.orderid);

or better yet with a join:

SELECT m1.* FROM marketorders m1 LEFT JOIN marketorders m2 ON 
m1.orderid=m2.orderid AND m1.reportedtime < m2.reportedtime 
WHERE m2.orderid IS NULL;

However, I just can't figure out how to do this with Django ORM. Is there any way to accomplish this without raw SQL?

EDIT: Just to clarify the problem. Let's say we have the following marketorders (leaving out everything unimportant and using only orderid, reportedtime):

1, 09:00:00
1, 10:00:00
1, 12:00:00
2, 09:00:00
2, 10:00:00

How do I get the following set with the ORM?

1, 12:00:00
2, 10:00:00

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

风和你 2024-08-11 23:45:08

如果我理解正确,您需要一个 Marketorder 对象列表,其中包含每个 orderid 具有最高报告时间的每个 Marketorder

类似的东西应该有效(免责声明:没有直接测试它):

m_orders = Marketorders.objects.filter(id__in=(
    Marketorders.objects
        .values('orderid')
        .annotate(Max('reportedtime'))
        .values_list('id', flat=True)
))

用于文档检查:

http://docs.djangoproject.com/en/dev/topics/db/aggregation/

编辑:
这应该得到一个针对特定订单 ID 具有最高报告时间的单一市价订单

order = (
    Marketorders.objects
        .filter(orderid=the_orderid)
        .filter(reportedtime=(
            Marketorders.objects
                .filter(orderid=the_orderid)
                .aggregate(Max('reportedtime'))
                ['reportedtime__max']
        ))
)

If I understood right you need a list of Marketorder objects that contains each Marketorder with highest reportedtime per orderid

Something like this should work (disclaimer: didn't test it directly):

m_orders = Marketorders.objects.filter(id__in=(
    Marketorders.objects
        .values('orderid')
        .annotate(Max('reportedtime'))
        .values_list('id', flat=True)
))

For documentation check:

http://docs.djangoproject.com/en/dev/topics/db/aggregation/

Edit:
This should get a single Marketorder with highest reportedtime for a specific orderid

order = (
    Marketorders.objects
        .filter(orderid=the_orderid)
        .filter(reportedtime=(
            Marketorders.objects
                .filter(orderid=the_orderid)
                .aggregate(Max('reportedtime'))
                ['reportedtime__max']
        ))
)
把回忆走一遍 2024-08-11 23:45:08

你有充分的理由不使用 ForeignKey 或(在您的情况下更好)ManyToManyField。这些字段代表了模型的关系结构。

此外,没有必要声明 pk-field id。如果没有定义 pk,django 会添加 id。

下面的代码允许像这样的 orm 查询:

   m1 = Marketorder()
   m1.save() # important: primary key will be added in db
   s1 = Snapshot()
   s2 = Snapshot()
   s1.save()
   s2.save()
   m1.snapshots.add(s1)
   m1.snapshots.add(s2)
   m1.snapshots.all()
   m1.snapshots.order_by("id") # snapshots in relations with m1 
                               # ordered by id, that is added automatically
   s1.marketorder_set.all()    # reverse

so for your query

snapshot = Snapshot.objects.order_by('-id')[0] # order desc, pick first
marketorders = snapshot.marketorder_set.all()  # all marketorders in snapshot

或紧凑

marketorders = Snapshot.objects.order_by('-id')[0].marketorder_set.all()

models.py

class Snapshot(models.Model):
    name = models.CharField(max_length=100)

class Marketorder(models.Model):
    snapshots = models.ManyToManyField(Snapshot)
    reportedtime = models.DateTimeField(auto_now= True)

按照惯例,所有模型类名称都是单一的。 Django 在不同的地方自动将其变为复数。

有关查询的更多信息(过滤、排序、复杂查找)。必读。

Do you have a good reason why you don't use ForeignKey or (in your case better) ManyToManyField. These fields represent the relational structure of ur models.

Furthermore it is not necessary to declare an pk-field id. if no pk is defined, django adds id.

The code below allow orm-queries like this:

   m1 = Marketorder()
   m1.save() # important: primary key will be added in db
   s1 = Snapshot()
   s2 = Snapshot()
   s1.save()
   s2.save()
   m1.snapshots.add(s1)
   m1.snapshots.add(s2)
   m1.snapshots.all()
   m1.snapshots.order_by("id") # snapshots in relations with m1 
                               # ordered by id, that is added automatically
   s1.marketorder_set.all()    # reverse

so for your query:

snapshot = Snapshot.objects.order_by('-id')[0] # order desc, pick first
marketorders = snapshot.marketorder_set.all()  # all marketorders in snapshot

or compact:

marketorders = Snapshot.objects.order_by('-id')[0].marketorder_set.all()

models.py:

class Snapshot(models.Model):
    name = models.CharField(max_length=100)

class Marketorder(models.Model):
    snapshots = models.ManyToManyField(Snapshot)
    reportedtime = models.DateTimeField(auto_now= True)

By convention all model classes name are singular. Django makes it plural in different places automatically.

more on queries (filtering, sorting, complex lookups). a must-read.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文