如何在Django中使用SELECT MAX?

Joh*_*hnd 75 django max django-models

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

我正在使用此代码:

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

rating是一个整数

Sas*_*gov 140

看到这个.您的代码将类似于以下内容:

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

如果您已经从数据库中获取了列表,那么您将执行以下操作:

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

这是未经测试的,所以我可能在某个地方犯了一个错误,但你去了.

  • 我需要具有Max的actuall参数对象,因此我可以打印详细信息字段.args.aggregate(Max('rating'))调用只返回最高评级.我正在寻找评价最高的arg. (4认同)
  • 亚当,我只是想知道是否有更好的方法 (2认同)

Lut*_*ann 67

Django还有' latest(field_name = None) '函数,用于查找最新(最大值)条目.它不仅适用于日期字段,还适用于字符串和整数.

您可以在调用该函数时给出字段名称:

max_rated_entry = YourModel.objects.latest('rating')
return max_rated_entry.details
Run Code Online (Sandbox Code Playgroud)

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

from django.db import models

class YourModel(models.Model):
    #your class definition
    class Meta:
        get_latest_by = 'rating'
Run Code Online (Sandbox Code Playgroud)

现在你可以在没有任何参数的情况下调用'latest()':

max_rated_entry = YourModel.objects.latest()
return max_rated_entry.details
Run Code Online (Sandbox Code Playgroud)

  • `latest()`和`earliest()`也适用于非日期字段,但它是实现的副作用.你应该使用`<your-queryset> .order_by('<interested-field>').first()`或`<your-queryset> .order_by('<interested-field>').last()`来确保即使Django开发人员将更改`latest()`和`earliest()`实现以仅处理日期字段,您的代码仍然有效. (5认同)
  • 这是使用`latest()`的好方法.如果你需要具有最小值的记录,你可以使用`earliest()`. (3认同)
  • 这是一个糟糕的答案:1)正如之前已经注意到的,它是实现的细节,并且可以在将来更改2)它的可读性不是很好 - 最大数量不一定是最新保存的一个(或在任何其他意义上) (2认同)

afa*_*him 41

我已经为我的项目测试了这个,它在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.all().aggregate(Max('rating'))['rating__max']
return App.objects.get(rating = max_rating)
Run Code Online (Sandbox Code Playgroud)

这可以保证有效地为您提供最大元素之一,而不是对整个表进行排序并获得顶部(在O(nlogn)附近).

  • Big-O有时在实践中并不值得,特别是对于较小的n,其中系数和实现很重要.您的代码位于python/django中,它被编译为字节码,可能会也可能不会被优化.数据库很可能用一种优化的语言编写,并编译成机器指令.此外,如果函数仅查找最大值,则数据库没有真正的排序理由.在我习惯使用内置数据库函数的手工构建代码之前,我想查看时序数据. (6认同)
  • @afahim 我不认为你发布的代码是完全正确的。如果事实证明您有多个最大值(假设您有两个 5 星的应用程序),则使用“get”将引发错误。 (6认同)

小智 13

溶胶01:

from .models import MyMODEL

max_rating = MyMODEL.objects.order_by('-rating').first()
Run Code Online (Sandbox Code Playgroud)

溶胶02:

from django.db.models import Max
from .models import MyMODEL

max_rating = MyMODEL.objects.aggregate(Max('rating'))
Run Code Online (Sandbox Code Playgroud)


ros*_*ori 8

如果您还想获取None表为空的情况以外的值(例如 0),请MaxCoalesce结合使用:

from django.db.models import Max, Value
from django.db.models.functions import Coalesce

max_rating = SomeModel.objects.aggregate(
    max_rating=Coalesce(Max('rating'), Value(0))
)['max_rating']
Run Code Online (Sandbox Code Playgroud)