Django过滤Window函数

Flo*_*etz 6 django django-models window-functions

我在Django,A和B中有两个模型.

每个A都有几个B分配给它,并且Bs是有序的,这是用字段B.order_index完成的,该字段从任何A的零向上计数.

我想写一个查询,检查是否有任何A,其中一些B有间隙或重复order_index值.

在SQL中,这可以这样做:

SELECT order_index, RANK() OVER(PARTITION BY a_id ORDER BY order_index ASC) - 1 AS rnk
WHERE rnk = order_index'
Run Code Online (Sandbox Code Playgroud)

但是,当我在Django中尝试使用此代码时:

B.objects.annotate(rank=RawSQL("RANK() OVER(PARTITION BY a_id ORDER BY order_index ASC) - 1", [])).filter(rank=F('order_index'))
Run Code Online (Sandbox Code Playgroud)

我收到一个错误说:

django.db.utils.ProgrammingError: window functions are not allowed in WHERE
LINE 1: ...- 1) AS "rank" FROM "main_b" WHERE (RANK() OVE...
Run Code Online (Sandbox Code Playgroud)

在SQL中,这很容易通过将整个事物包装在子查询中并将Where子句应用于该子查询来修复.我怎样才能在Django中做同样的事情?

Car*_*arl -2

我还没有测试过这个,但是使用 @Bobort 评论中提到的新窗口函数,你可以尝试这样的方法,它生成的 SQL 非常接近你想要的,除了“-1”之外

from django.db.models import F
from django.db.models.expressions import Window
from django.db.models.functions import Rank

B.objects.annotate(rank=Window(
    expression=Rank(),
    order_by=F('order_index').desc(),
    partition_by=[F('a_id')]))
Run Code Online (Sandbox Code Playgroud)