Python Django 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

作为回答,我认为窗口函数不允许与filter组合(从技术上讲,是这样的,但是filter子句会影响窗口)。有一个在内部查询中包装窗口函数的提示,因此最终的SQL如下所示(据我所知):

问题是:我如何用Django ORM编写这个查询?

但是现在用ORM是不可能的


一个建议的解决方案是添加一个
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'