Django QuerySet 二值子查询

标签 django django-queryset

给定一个模型

class Entity(models.Model):
    identifier = models.IntegerField()
    created = models.IntegerField()
    content = models.IntegerField()

    class Meta:
        unique_together = (('identifier', 'created'))

我想用 created 查询所有对象在具有共同点的对象中最大 identifier .

在 SQL 中,子查询中的窗口函数解决了这个问题:
SELECT identifier, content
  FROM entity
  WHERE (identifier, created)
    IN (SELECT identifier, max(created) OVER (PARTITION BY identifier)
          FROM entity);

另见:http://sqlfiddle.com/#!17/c541f/1/0

窗口函数和子查询在 Django 2.0 中都可用。但是,我还没有找到用多列表达子查询表达式的方法。

有没有办法将该 SQL 查询转换为 Django QuerySet 世界?这可能是一个 XY 问题,我的问题可以用不同的方式解决吗?

我丑陋的解决方法是
Entity.objects.raw('''
SELECT * FROM app_entity e
 WHERE e.created = (SELECT max(f.created) FROM app_entity f WHERE e.identifier = f.identifier)''')

因为底层的 sqlite3 版本显然无法处理多列子查询。

最佳答案

我认为你可以用另一种方式来做(但我不确定它是否会比窗口表达式表现得更好或更差)......

max_created = Entity.objects.filter(
    identifier=OuterRef('identifier')
).order_by('-created').values('created')[:1]

Entity.objects.filter(
    created=Subquery(max_created)
)

这个抢了最大的created给定值 identifier ,作为相关子查询,然后只过滤那些匹配的。

这可能需要调整:我不确定您是否可以像这样过滤子查询,或者您是否需要 .annotate(max_created=Subquery(created)).filter(created=F('max_created'))或者其他类似的可怕的东西。

另外,如果你使用的是 postgres,你可以使用 DISTINCT ON获得一个非常简洁的解决方案的功能:
Entity.objects.order_by('identifier', '-created').distinct('identifier')

关于Django QuerySet 二值子查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50407055/

相关文章:

python - 我得到了查询集,如何获取相关对象?

django - 计算 Django 查询集中相同的字段值

django - nginx 缓存,staticgenerator 与 memcached

python - 基于 Django 类的 View 出现错误 : 'get_context_data() keywords must be strings'

django - 以自定义表单呈现模板中的各个字段

django - 如何在 Django Admin 的 list_display 属性中定位内联?

python - 如何测试 Django QuerySets 是否相等?

python - Django 中的可重用模态成员

python - 如何将数据库查询集对象从基于类的 View 传递到 Django 2.0 中的模板

python - 一一获取查询集数据