如何在Django中执行SELECT MAX?


91

我有一个对象列表,如何运行查询以给出字段的最大值:

我正在使用此代码:

def get_best_argument(self):
    try:
        arg = self.argument_set.order_by('-rating')[0].details
    except IndexError:
        return 'no posts'
    return arg

评分是整数

Answers:


172

看到这个。您的代码将如下所示:

from django.db.models import Max
# Generates a "SELECT MAX..." query
Argument.objects.aggregate(Max('rating')) # {'rating__max': 5}

您还可以在现有的查询集上使用它:

from django.db.models import Max
args = Argument.objects.filter(name='foo') # or whatever arbitrary queryset
args.aggregate(Max('rating')) # {'rating__max': 5}

如果您需要包含此最大值的模型实例,则发布的代码可能是实现此目的的最佳方法:

arg = args.order_by('-rating')[0]

请注意,如果queryset为空,即没有参数匹配查询,这将出错(因为该[0]部分将引发IndexError)。如果要避免这种行为,而只是None在这种情况下返回,请使用.first()

arg = args.order_by('-rating').first() # may return None

4
我需要具有那个Max的actuall参数对象,因此我可以打印详细信息字段。args.aggregate(Max('rating'))调用仅返回最高评分。我正在寻找收视率最高的arg。
约翰德,2009年

1
您的退出代码-Argument.objects.order_by(“-rating”)[0]有什么问题?
09年

73

Django也有' Latest(field_name = None) ”函数,该函数可查找最新(最大值)条目。它不仅适用于日期字段,而且适用于字符串和整数。

您可以在调用该函数时提供字段名称:

max_rated_entry = YourModel.objects.latest('rating')
return max_rated_entry.details

或者您已经可以在模型元数据中提供该字段名称:

from django.db import models

class YourModel(models.Model):
    #your class definition
    class Meta:
        get_latest_by = 'rating'

现在,您无需任何参数即可调用“ latest()”:

max_rated_entry = YourModel.objects.latest()
return max_rated_entry.details

3
这是使用的好方法latest()。如果需要最小值的记录,可以使用earliest()
SaeX

7
latest()并且也earliest()可以与非日期字段一起使用,但这是实施的副作用。您应该使用<your-queryset>.order_by('<interested-field>').first()<your-queryset>.order_by('<interested-field>').last()确保即使Django开发人员将更改latest()并且earliest()实现仅与日期字段一起使用,您的代码仍然可以使用。
mrnfrancesco '17

这是一个不好的答案:1)前面已经注意到它的实现细节,并且可以在以后更改2)它不是很可读-最大数量不一定是最新保存的一个(或任何其他含义)
Mikhail Gerasimov

47

我已经为我的项目进行了测试,它找到了O(n)时间的最大值/最小值:

from django.db.models import Max

# Find the maximum value of the rating and then get the record with that rating. 
# Notice the double underscores in rating__max
max_rating = App.objects.aggregate(Max('rating'))['rating__max']
return App.objects.get(rating=max_rating)

这样可以保证使您高效地获得最大的元素之一,而不是对整个表进行排序并获得顶部(大约O(n * logn))。


8
在实践中,Big-O有时并不适用,尤其是对于较小的n而言,系数和实现很重要。您的代码位于python / django中,已编译为字节码,并且可能会或可能不会进行优化。该数据库很可能以经过优化并编译为机器指令的语言编写。此外,如果函数仅在寻找最大值,则数据库没有排序的真正理由。我想在适合通过内置数据库功能使用手动构建代码之前先查看时序数据。
benevolentprof

5
@afahim我认为您发布的代码完全不正确。如果事实证明您有多个最大值(例如,您有两个具有5星的应用),则使用“获取”会引发错误。
雷德尔·米兰达
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.