这是我的查询,它给出了所有用户的排名:
rank = Wallet.objects.filter(type=0, space_id=space.id).annotate(
rank=Window(
expression=DenseRank(),
order_by=F('point_amount').desc(),
)
).order_by('rank').values("user__id","user__username","rank")
但是我怎样才能获得这个查询中特定用户的排名?(我不想处理这个python)
我已经尝试过这个:
rank = Wallet.objects.filter(type=0, space_id=space.id, user_id=user.id).annotate(
rank=Window(
expression=DenseRank(),
order_by=F('point_amount').desc(),
)
).order_by('rank').values("user__id","user__username","rank")
但它给了我排名 1,这是不正确的
注意: 这个原始查询给了我正确的答案,但我不知道如何将其转换为 django orm 查询
query = f'''
SELECT
FIND_IN_SET(
`transaction_wallet`.`point_amount`,
(
SELECT
GROUP_CONCAT(`transaction_wallet`.`point_amount` ORDER BY `transaction_wallet`.`point_amount` DESC)
FROM `transaction_wallet`
WHERE `transaction_wallet`.`type` = 0 AND `transaction_wallet`.`space_id` = {space.id}
)
) AS `rank`
FROM
`transaction_wallet`
WHERE
`transaction_wallet`.`type` = 0 AND `transaction_wallet`.`space_id` = {space.id} AND `transaction_wallet`.`user_id` = {self.id};
'''
```
Django 查询集是惰性的。在需要时对它们进行评估。这意味着当执行查询时,
user_id
过滤器将查询集限制为单个对象,然后评估窗口函数。结果是 rank
的 1
值。
要解决此问题,您必须首先构建不带 user_id
过滤器的查询,让 django 执行查询(包括注释),然后应用 user_id
过滤器。
# Step 1: Build the annotated query
rank = (Wallet
.objects
.filter(type=0, space_id=space.id)
.annotate(rank=Window(expression=DenseRank(),
order_by=F('point_amount').desc())
.order_by('rank'))
# Step 2: Evaluate the query
rank.count()
# Step 3: Now apply the filter
ranked_user_wallet = rank.filter(user_id=user.id)
# Now ranked_user_wallet is a single Wallet object of the desired user
# with the correct rank annotation applied