Найти - Пользователи
Полная версия: ORM выборка с учетом значений в нескольких строках
Начало » Django » ORM выборка с учетом значений в нескольких строках
1 2
well
Всем привет! Стоит у меня следующая задача. Есть таблица:
from django.db import models
class AllElements (models.Model):
elem_name = models.CharField (max_length=25)
elem_value = models.IntegerField()
elem_name могут повторяться. Нужно сгруппировать поля по elem_name при этом брать именно то, у которого elem_value максимальное для данного elem_name. Потом еще будет накладываться фильтр по elem_value. Надеюсь, внятно объяснил :). Реально ли такое реализовать с помощью django ORM?
regall
По идее так:
from django.db.models import Max
result = AllElements.objects.all().aggregate(Max('elem_value'))
well
regall
По идее так:
from django.db.models import Max
result = AllElements.objects.all().aggregate(Max('elem_value'))
Так я получу просто максимальное значение elem_value, а мне нужно при этом еще сделать группировку по elem_name и получить максимальное значение elem_value для каждого elem_name. Вот, как этот запрос выглядит на зыке SQL (Oracle):
select elem_name, max(elem_value) m_elemv from table_name
group by elem_name order by m_elemv
svas
Попробуйте так
AllElements.objects.values('elem_name').annotate(max_elem_value=Max('elem_value'))
well
svas
Попробуйте так
AllElements.objects.values('elem_name').annotate(max_elem_value=Max('elem_value'))
Тут запрос будет проводить группировку по паре elem_name и elem_value, следовательно я получу одинаковые elem_name, если у них будут разные elem_value
razum2um
по моему я вас огорчу. была та же задача.
http://stackoverflow.com/questions/3508818/django-how-do-i-explicitly-make-a-query-with-a-having-clause
алсо сделал rawsql
svas
Ordinarily, annotations are generated on a per-object basis - an annotated QuerySet will return one result for each object in the original QuerySet. However, when a values() clause is used to constrain the columns that are returned in the result set, the method for evaluating annotations is slightly different. Instead of returning an annotated result for each result in the original QuerySet, the original results are grouped according to the unique combinations of the fields specified in the values() clause. An annotation is then provided for each unique group; the annotation is computed over all members of the group.
Не знаю почему вы решили что будет проводится группировка по паре. Сам не пробовал, но судя по документации должно работать.
well
svas
Ordinarily, annotations are generated on a per-object basis - an annotated QuerySet will return one result for each object in the original QuerySet. However, when a values() clause is used to constrain the columns that are returned in the result set, the method for evaluating annotations is slightly different. Instead of returning an annotated result for each result in the original QuerySet, the original results are grouped according to the unique combinations of the fields specified in the values() clause. An annotation is then provided for each unique group; the annotation is computed over all members of the group.
Не знаю почему вы решили что будет проводится группировка по паре. Сам не пробовал, но судя по документации должно работать.
Я попробовал - вернуло все уникальные значения по паре и проверил запрос - он был на уникальность пары :(
razum2um
по моему я вас огорчу. была та же задача.
http://stackoverflow.com/questions/3508 … ing-clause
алсо сделал rawsql
Спасибо за ссылку, видать, тоже прийдется raw-sql. Хотя, там стоит немного другая задача, если я првильно понял тот запрос.
svas
class AllElements(models.Model):
elem_name = models.CharField(max_length=25)
elem_value = models.IntegerField()

def __unicode__(self):
return u'%s, %s' % (self.elem_name, self.elem_value)
>>> from django.db.models import Max
>>> e = AllElements(elem_name = 'qwe', elem_value=1)
>>> e.save()
>>> e = AllElements(elem_name = 'qwe', elem_value=2)
>>> e.save()
>>> e = AllElements(elem_name = 'qwe', elem_value=3)
>>> e.save()
>>> e = AllElements(elem_name = 'asd', elem_value=4)
>>> e.save()
>>> e = AllElements(elem_name = 'asd', elem_value=5)
>>> e.save()
>>> e = AllElements(elem_name = 'qwe', elem_value=3)
>>> e.save()
>>> AllElements.objects.all()
[<AllElements: qwe, 1>, <AllElements: qwe, 2>, <AllElements: qwe, 3>, <AllElements: asd, 4>, <AllElements: asd, 5>, <AllElements: qwe, 3>]
>>> AllElements.objects.all().values('elem_name').annotate(max_elem_value = Max('elem_value'))
[{'max_elem_value': 5, 'elem_name': u'asd'}, {'max_elem_value': 3, 'elem_name': u'qwe'}]
>>>
Может я не понимаю что вам действительно нужно?
well
svas
class AllElements(models.Model):
elem_name = models.CharField(max_length=25)
elem_value = models.IntegerField()

def __unicode__(self):
return u'%s, %s' % (self.elem_name, self.elem_value)
>>> from django.db.models import Max
>>> e = AllElements(elem_name = 'qwe', elem_value=1)
>>> e.save()
>>> e = AllElements(elem_name = 'qwe', elem_value=2)
>>> e.save()
>>> e = AllElements(elem_name = 'qwe', elem_value=3)
>>> e.save()
>>> e = AllElements(elem_name = 'asd', elem_value=4)
>>> e.save()
>>> e = AllElements(elem_name = 'asd', elem_value=5)
>>> e.save()
>>> e = AllElements(elem_name = 'qwe', elem_value=3)
>>> e.save()
>>> AllElements.objects.all()
[<AllElements: qwe, 1>, <AllElements: qwe, 2>, <AllElements: qwe, 3>, <AllElements: asd, 4>, <AllElements: asd, 5>, <AllElements: qwe, 3>]
>>> AllElements.objects.all().values('elem_name').annotate(max_elem_value = Max('elem_value'))
[{'max_elem_value': 5, 'elem_name': u'asd'}, {'max_elem_value': 3, 'elem_name': u'qwe'}]
>>>
Может я не понимаю что вам действительно нужно?
Прошу прощения, я невнимательно применил у себя ваш пример и потому получил на выходе неверный запрос. Ваш ответ как раз то, что нужно. Спасибо большое!
Поясню свою ошибку: у меня так же были еще поля в таблице и по одному из них велась сортировка по умолчанию, т.е. модель моя имела вид:
class AllElements(models.Model):
elem_name = models.CharField(max_length=25)
elem_value = models.IntegerField()
elem_other = model.CharField (max_length=25, unique=True)

def __unicode__(self):
return u'%s, %s' % (self.elem_name, self.elem_value)
class Meta:
ordering = ['elem_other']
Потому мне пришлось немного дополнить запрос, до чего я сразу не дошел:
AllElements.objects.all().values('elem_name').annotate(max_elem_value = Max('elem_value')).order_by('elem_name')
Еще раз простите за невнимательность и спасибо за настойчивость!
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB