Django 对窗口函数进行过滤

标签 django django-models window-functions

我在 Django 中有两个模型,AB

每个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/

相关文章:

python - 如何使用 Django 中基于类的通用 View 将父 id 作为 fk 传递给子对象的 ModelForm?

python - 记录 Django 用户事件的正确方法

Django - Slug 字段对于用户必须是唯一的,但对于所有用户来说不是唯一的

sql - 在 Postgresql 上配对顺序事件

sql - SQLite3中的窗口函数

python - 为什么 Django 的 HTTPResponseRedirect 对 PUT 使用相同的 HTTP 方法而不是 POST?

python - 记录更改列表中的 Django-admin : How to display link to object info page instead of edit form ,?

javascript - 如果模型中不存在数据,则使用 django 保存数据,如果数据存在则更新

sql - 按 SQL 中的第一个值对行序列进行分组

django - UpdateView 中的多个模型