ChatGPT解决这个技术问题 Extra ChatGPT

如何在 Django 中执行 SELECT MAX?

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

我正在使用这段代码:

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

评级是一个整数


S
Sasha Chedygov

请参阅this。您的代码将类似于以下内容:

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]

请注意,如果查询集为空,即没有参数与查询匹配,这将出错(因为 [0] 部分将引发 IndexError)。如果您想避免这种行为并在这种情况下简单地返回 None,请使用 .first()

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

我需要具有该 Max 的实际参数对象,因此我可以打印详细信息字段。 args.aggregate(Max('rating')) 调用只返回最高评级。我正在寻找评分最高的 arg。
您的现有代码有什么问题 - Argument.objects.order_by("-rating")[0]?
L
Lutz Schönemann

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

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

我已经为我的项目测试了这个,它在 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))。


Big-O 有时在实践中并不奏效,特别是对于较小的 n,其中系数和实现很重要。您的代码在 python/django 中,它被编译为字节码,可能会也可能不会优化。数据库可能是用一种经过优化并编译为机器指令的语言编写的。此外,如果函数只是在寻找最大值,那么数据库没有真正的排序理由。在我习惯于在内置数据库函数上使用手动构建代码之前,我想查看计时数据。
@afahim 我认为您发布的代码不完全正确。如果事实证明你有超过一个最大值(假设你有两个 5 星的应用程序)使用“get”将引发错误。
这种方法的另一个问题是,通常不能保证在计算最大值之后,在查询之前没有删除带有它的记录。为确保这一点,您需要在事务中执行这两个数据库语句,同时使用 select_for_update 锁定整个表,这对数据库有很大的性能影响。
D
Dipta Dhar

溶胶 01:

from .models import MyMODEL

max_rating = MyMODEL.objects.order_by('-rating').first()

溶胶 02:

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

max_rating = MyMODEL.objects.aggregate(Max('rating'))

r
roskakori

如果您还想在表为空的情况下获取 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']

S
Sona Pochybova

如果您想要随机评论,可能会改进关于@Raydel Miranda 评论的@afahim 答案。如果你想要全部,那么只使用过滤器

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.filter(rating=max_rating).first()

Z
ZeQ

也许它会帮助某人的麻烦

def get_queryset(self):
    sorgu = Sunum.objects.values('id', 'firma', 'projeadi', 'sunumdurum__durum', 'sunumdurum__aciklama'
                           ).annotate(max_rank=Max('sunumdurum__kayittarihi'))
    szlk={}
    for sor in sorgu :
        ana = sor['id'], sor['firma'], sor['projeadi']
        dana = sor['sunumdurum__durum'], sor['sunumdurum__aciklama'], sor['max_rank']
        szlk.setdefault(ana, dana)
    return szlk