给定一个模型
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/