Django ORM:获取不同领域的最新记录

时间:2017-07-24 19:00:43

标签: python sql django

我在将一些SQL转换为Django时遇到了麻烦。

想象一下,我们有一些汽车,每辆汽车都有一个独特的VIN,我们用其他一些数据记录它们在车间的日期。 (请忽略一个人可能以这种方式构建数据的原因。这是专门针对这个问题。:-))

class ShopVisit(models.Model):
    vin = models.CharField(...)
    date_in_shop = models.DateField(...)
    mileage = models.DecimalField(...)
    boolfield = models.BooleanField(...)

我们希望单个查询返回一个Queryset,其中包含每个vin的最新记录并更新它!

special_vins = [...]

# Doesn't work
ShopVisit.objects.filter(vin__in=special_vins).annotate(max_date=Max('date_in_shop').filter(date_in_shop=F('max_date')).update(boolfield=True)

# Distinct doesn't work with update
ShopVisit.objects.filter(vin__in=special_vins).order_by('vin', '-date_in_shop).distinct('vin').update(boolfield=True)

是的,我可以遍历查询集。但这并不是非常有效,而且我需要很长时间来处理大约2M的记录。可以执行此操作的SQL如下(我认为!):

SELECT *
FROM cars
INNER JOIN (
   SELECT MAX(dateInShop) as maxtime, vin
   FROM cars
   GROUP BY vin
) AS latest_record ON (cars.dateInShop= maxtime)
   AND (latest_record.vin = cars.vin)

那么我怎么能用Django来实现呢?

2 个答案:

答案 0 :(得分:1)

这有点未经测试,并且依赖于Django 1.11进行子查询,但可能类似于:

latest_visits = Subquery(ShopVisit.objects.filter(id=OuterRef('id')).order_by('-date_in_shop').values('id')[:1])

ShopVisit.objects.filter(id__in=latest_visits)

我有一个类似的模型,所以去测试它但得到了一个错误: “此版本的MySQL尚不支持'LIMIT& IN / ALL / ANY / SOME子查询”

它生成的SQL看起来很像你想要的,所以我觉得这个想法很合理。如果你使用PostGres,也许它支持那种类型的子查询。

这是它生成的SQL(修剪了一些并用假的替换了实际名称):

SELECT `mymodel_activity`.* FROM `mymodel_activity` WHERE `mymodel_activity`.`id` IN (SELECT U0.`id` FROM `mymodel_activity` U0 WHERE U0.`id` = (`mymodel_activity`.`id`) ORDER BY U0.`date_in_shop` DESC LIMIT 1)

答案 1 :(得分:0)

我想知道你是否自己找到了解决方案。

我只能提出原始查询字符串。 Django Raw SQL query Manual

UPDATE "yourapplabel_shopvisit" 
SET boolfield = True WHERE date_in_shop 
IN (SELECT MAX(date_in_shop) FROM "yourapplabel_shopvisit" GROUP BY vin);