我在 Django 中有两个模型,A
和 B
。
每个A
都分配有多个B
,并且B
是有序的,这是通过字段完成的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'
但是,当我使用以下代码在 Django 中尝试此操作时:
B.objects.annotate(rank=RawSQL("RANK() OVER(PARTITION BY a_id ORDER BY order_index ASC) - 1", [])).filter(rank=F('order_index'))
我收到一条错误消息:
django.db.utils.ProgrammingError: window functions are not allowed in WHERE
LINE 1: ...- 1) AS "rank" FROM "main_b" WHERE (RANK() OVE...
在 SQL 中,通过将整个内容包装在子查询中并将Where子句应用于该子查询,可以很容易地解决这个问题。我怎样才能在 Django 中做同样的事情?
最佳答案
表达此类查询的一种可能的解决方法是使用 https://github.com/dimagi/django-cte 。
from django_cte import With
cte = With(
B.objects.all().annotate(
rank=Window(
expression=Rank(),
partition_by=F('a_id'),
order_by=F('order_index').asc()
)
)
)
cte.join(B.objects.all(), id=cte.col.id).with_cte(cte).annotate(
rank=cte.col.rank
).filter(
rank=F('order_index')
)
关于Django 对窗口函数进行过滤,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46245123/