You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Django QuerySet添加子查询最大值之和的注解

Django ORM实现Top实例注解:计算指定klass下Lower最大rank之和

模型定义(明确结构)

from django.db import models

class Top(models.Model):
    name = models.CharField(max_length=100, unique=True)

class Middle(models.Model):
    name = models.CharField(max_length=100, unique=True)
    top = models.ForeignKey(Top, on_delete=models.CASCADE, related_name='middles')

class Lower(models.Model):
    klass = models.CharField(max_length=100)
    name = models.CharField(max_length=100)
    rank = models.IntegerField()
    middle = models.ForeignKey(Middle, on_delete=models.CASCADE, related_name='lowers')

    class Meta:
        unique_together = ('klass', 'name', 'middle')

解决方案

1. 计算所有klass下的最大rank之和

通过嵌套子查询先分组获取每个(klass, name)的最大rank,再对当前Top下的所有分组值求和:

from django.db.models import Subquery, OuterRef, Max, Sum

# 子查询:获取当前Top下所有Middle关联Lower的(klass, name)分组最大rank
grouped_max_ranks = Lower.objects.filter(
    middle__top=OuterRef('pk')
).values('klass', 'name').annotate(
    max_rank=Max('rank')
).values('max_rank')

# 为Top实例注解求和结果并排序
tops = Top.objects.annotate(
    sum_highest_ranks=Sum(Subquery(grouped_max_ranks))
).order_by('-sum_highest_ranks')

2. 计算指定klass下的最大rank之和

只需在子查询中添加klass过滤条件,同时调整分组字段(仅按name分组):

target_klass = "target_class_name"

grouped_max_ranks_filtered = Lower.objects.filter(
    middle__top=OuterRef('pk'),
    klass=target_klass
).values('name').annotate(
    max_rank=Max('rank')
).values('max_rank')

tops_filtered = Top.objects.annotate(
    sum_highest_ranks=Sum(Subquery(grouped_max_ranks_filtered))
).order_by('-sum_highest_ranks')

关键说明

之前用Subquery仅返回单个最大值的问题,是因为子查询没有正确返回当前Top下所有分组的最大rank列表。上面的写法通过values('klass', 'name')(或指定klass时的values('name'))完成分组,确保子查询返回所有符合条件的max_rank值,外层Sum就能正确累加所有分组的最大值。

内容的提问来源于stack exchange,提问作者Bernd Wechner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 06:15:22