根据子查询在同一模型上生成的行数更新Django模型

2024-04-25 14:13:06 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个PostgreSQLUPDATE查询,它根据同一个表中每一行的ROW_NUMBER()按另一个字段(rating)排序,更新表中每一行的一个字段(global_ranking)。此外,更新是分区的,因此每一行的排名仅与那些属于相同language的行相关

简而言之,我正在更新游戏中每个玩家的排名,基于他们当前的评级

PostgreSQL查询如下所示:

UPDATE stats_userstats
SET    
    global_ranking = sub.row_number
FROM  (
    SELECT id, ROW_NUMBER() OVER (
        PARTITION BY language
        ORDER BY rating DESC
    ) AS row_number
    FROM stats_userstats
) sub
WHERE stats_userstats.id = sub.id;

我也在使用Django,如果可能的话,学习如何使用Django ORM表达这个查询会很有趣

Django似乎拥有表达查询所需的一切,包括使用PostgreSQL的ROW_NUMBER()窗口函数的能力,但我当前的尝试是使用1更新所有行ranking

from django.db.models import F, OuterRef, Subquery
from django.db.models.expressions import Window
from django.db.models.functions import RowNumber

UserStats.objects.update(
    global_ranking=Subquery(
        UserStats.objects.filter(
            id=OuterRef('id')
        ).annotate(
            row_number=Window(
                expression=RowNumber(),
                partition_by=[F('language')],
                order_by=F('rating').desc()
            )
        ).values('row_number')
    )
)

我使用from django.db import connection; print(connection.queries)来查看由Django ORM语句生成的查询,并得到了这个模糊相似的SQL语句:

UPDATE "stats_userstats" 
SET "global_ranking" = (
    SELECT ROW_NUMBER() OVER (
        PARTITION BY U0."language"
        ORDER BY U0."rating" DESC
    ) AS "row_number" 
FROM "stats_userstats" U0 
WHERE U0."id" = "stats_userstats"."id"

看起来我需要做的是将子查询从查询的SET部分移动到FROM,但我不清楚如何重新构造Django ORM语句来实现这一点

非常感谢您的帮助,我会在游戏结束后留下评论,并附上游戏链接:)谢谢


Tags: djangofromidnumberbystatsgloballanguage