Как сделать SELECT MAX в Django?
У меня есть список объектов, как я могу выполнить запрос, чтобы дать максимальное значение поля:
Я использую этот код:
def get_best_argument(self):
try:
arg = self.argument_set.order_by('-rating')[0].details
except IndexError:
return 'no posts'
return arg
рейтинг является целым числом
8 ответов
Смотрите это. Ваш код будет выглядеть примерно так:
from django.db.models import Max
# Generates a "SELECT MAX..." statement
Argument.objects.all().aggregate(Max('rating'))
Если вы уже получили список из базы данных, вы бы сделали что-то вроде этого:
from django.db.models import Max
args = Argument.objects.all()
# Calculates the maximum out of the already-retrieved objects
args.aggregate(Max('rating'))
Это не проверено, поэтому я, возможно, где-то допустил ошибку, но вы идете.
Django также имеет функцию " последний (имя_поля = 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
Я проверил это для своего проекта, он находит максимальное / минимальное время 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)
Это гарантированно даст вам один из максимальных элементов, вместо того, чтобы сортировать всю таблицу и получать верх (около O(nlogn)).
соль 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'))
Если вы также хотите получить значение, отличное от
None
если таблица пуста (например, 0), объедините
Max
с Coalesce:
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']
Чтобы, возможно, улучшить ответ @afahim в отношении комментария @Raydel Miranda, если вам нужен случайный комментарий. Если хотите все, используйте только фильтр
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()
может кому поможет в беде
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
Для будущих читателей вы можете использоватьannotate
вместоaggregate
если вам нужны записи/другие поля, а не только максимальное значение.
т.е. эквивалентно этому SQL-запросу
SELECT
first_name,
last_name,
Max(height) max_height
FROM patients;
Теперь одна проблема заключается в том, что передача агрегатной функции в аннотации вызовет группу по
from django.db.models import Max
Patients.objects.values('height').annotate(max_height=Max('height'))
>>>
SELECT "patients"."height",
MAX("patients"."height") AS "max_height"
FROM "patients"
GROUP BY "patients"."height"
Обходной путь — использовать выражение Func.
from django.db.models F, Func
Patients.objects.annotate(max_height=Func(F('height'), function='Max'))\
.values('first_name', 'last_name', 'max_height')
>>>
SELECT "patients"."first_name",
"patients"."last_name",
Max("patients"."height") AS "max_height"
FROM "patients"
посмотрите это , если вам нужно сделать это в подзапросе