Python Django ORM:带有后续筛选的窗口函数
作为回答,我认为窗口函数不允许与filter组合(从技术上讲,是这样的,但是filter子句会影响窗口)。有一个在内部查询中包装窗口函数的提示,因此最终的SQL如下所示(据我所知): 问题是:我如何用Django ORM编写这个查询?但是现在用ORM是不可能的Python Django ORM:带有后续筛选的窗口函数,python,django,django-orm,Python,Django,Django Orm,作为回答,我认为窗口函数不允许与filter组合(从技术上讲,是这样的,但是filter子句会影响窗口)。有一个在内部查询中包装窗口函数的提示,因此最终的SQL如下所示(据我所知): 问题是:我如何用Django ORM编写这个查询?但是现在用ORM是不可能的 一个建议的解决方案是添加一个QuerySet.subquery()或.wrap()方法,将查询集推送到子查询中,以便对其进行过滤。您需要使用原始查询。以便一次执行多个查询。欲知详情 你可以做的其他事情如下 model.py class C
一个建议的解决方案是添加一个
QuerySet.subquery()
或.wrap()
方法,将查询集推送到子查询中,以便对其进行过滤。您需要使用原始查询。以便一次执行多个查询。欲知详情
你可以做的其他事情如下
model.py
class Category(models.Model):
name = models.CharField(max_length=100)
class Hero(models.Model):
# ...
name = models.CharField(max_length=100)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
benevolence_factor = models.PositiveSmallIntegerField(
help_text="How benevolent this hero is?",
default=50
)
querySet.py
hero_qs = Hero.objects.filter(category=OuterRef("pk"))
.order_by("-benevolence_factor")
Category.objects.all()
.annotate(most_benevolent_hero=Subquery(hero_qs.values('name')[:1]))
生成的SQL如下所示
SELECT "entities_category"."id",
"entities_category"."name",
(SELECT U0."name"
FROM "entities_hero" U0
WHERE U0."category_id" = ("entities_category"."id")
ORDER BY U0."benevolence_factor" DESC
LIMIT 1) AS "most_benevolent_hero"
FROM "entities_category"
另一种解决方案是通用表表达式(CTE),在的帮助下,您可以实现您想要的:
cte = With(
YouModel.objects.annotate(
your_window_function=Window(...),
)
)
qs = cte.queryset().with_cte(cte).filter(your_window_function='something')
这大致可以理解为:
WITH cte as (
SELECT *, WINDOW(...) as your_window_function
FROM yourmodel
)
SELECT *
FROM cte
WHERE cte.your_window_function = 'something'
我也有同样的问题。这在postgres中是可能的(见文档底部),但我不知道如何将其转换为ORM。有人知道吗?@ilse2005给定的表达式更像是
SELECT。。。FROM(子查询\表达式)作为foo
。幸运的是,Django有表达式,但它没有提供从子句指定的功能。据我所知,这是一个窗口表达式问题,而不是一个窗口表达式问题。谢谢!但遗憾的是,使用原始sql不是一种选择。另外,对于我的用例来说,添加一个额外的字段并不是一个很好的解决方案。你能详细说明一下吗?你有没有在带有窗口函数注释的查询集上进行过滤的例子?ORM目前不支持它,但其想法是添加一个子查询
方法,将当前查询集包装在SELECT*FROM(queryset\u query)中作为window\u子查询
,后续过滤器可以针对window\u子查询
生成其中
。
cte = With(
YouModel.objects.annotate(
your_window_function=Window(...),
)
)
qs = cte.queryset().with_cte(cte).filter(your_window_function='something')
WITH cte as (
SELECT *, WINDOW(...) as your_window_function
FROM yourmodel
)
SELECT *
FROM cte
WHERE cte.your_window_function = 'something'