Django ORM:分组和SQL Agregation

时间:2018-03-10 21:40:38

标签: sql django django-models django-orm

我知道那里存在任何相同的主题,但这并没有描述我的情况:(

我有一个模型如下:

class SecurityPrice (models.Model):
    security    = models.ForeignKey(Security, on_delete = models.CASCADE)
    created     = models.DateTimeField()
    price       = models.FloatField()

    class Meta:
        ordering = ('-created',)

    def __unicode__(self):
        return u'%s - %s - %s' % (self.created, self.security.ticker, self.price)

或在sqlite中:

CREATE TABLE IF NOT EXISTS "restful_api_securityprice" 
("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, 
"created" datetime NOT NULL, 
"price" real NOT NULL, 
"security_id" integer NOT NULL REFERENCES "restful_api_security" ("id"));

我想为每份证券文件选择最后价格

在原始SQL中,我可以使用这样的SQL请求来执行此操作:

SELECT MAX(created), security_id, price as created 
FROM restful_api_securityprice GROUP BY security_id;

以下一些示例了解我的需求:

表格中的所有记录

sqlite> SELECT * FROM restful_api_securityprice;
1|2018-01-07 23:13:02|920.0|1
2|2018-01-07 23:13:43|137.12|2
3|2018-01-07 23:13:58|147.3|3
4|2018-01-09 00:46:29|920.0|1
5|2018-01-09 00:47:27|137.12|2
6|2018-01-09 00:48:08|147.3|3

我需要的东西

sqlite> SELECT MAX(created), security_id, price as created FROM restful_api_securityprice GROUP BY security_id;
2018-01-09 00:46:29|1|920.0
2018-01-09 00:47:27|2|137.12
2018-01-09 00:48:08|3|147.3

在原始SQL中它没问题。但是如何在没有包含原始sql的情况下在Django ORM API中做同样的事情呢?

2 个答案:

答案 0 :(得分:0)

如下查询:

SecurityPrice.objects.order_by('security', '-created').distinct('security')

答案 1 :(得分:0)

试试这个,

from django.db.models import Max

SecurityPrice.objects.values('security_id').annotate(Max('created'))


示例

In [12]: from django.db.models import Max

In [13]: from app_name.models import SecurityPrice

In [14]: aggregation = SecurityPrice.objects.values('security_id').annotate(Max('created'))

In [15]: aggregation
Out[15]: <QuerySet [{'security_id': 1, 'created__max': datetime.datetime(2019, 3, 11, 6, 51, 23, tzinfo=<UTC>)}, {'security_id': 1, 'created__max': datetime.datetime(2018, 3, 11, 6, 51, 13, tzinfo=<UTC>)}]>

In [16]: print(aggregation.query)
SELECT "app_name_securityprice"."security_id", MAX("app_name_securityprice"."created") AS "created__max" FROM "app_name_securityprice" GROUP BY "app_name_securityprice"."security_id", "app_name_securityprice"."created" ORDER BY "app_name_securityprice"."created" DESC