Уведомления

Группа в Telegram: @pythonsu
  • Начало
  • » Django
  • » ORM выборка с учетом значений в нескольких строках [RSS Feed]

#1 Ноя. 1, 2010 21:43:57

well
От:
Зарегистрирован: 2006-11-20
Сообщения: 163
Репутация: +  0  -
Профиль   Отправить e-mail  

ORM выборка с учетом значений в нескольких строках

Всем привет! Стоит у меня следующая задача. Есть таблица:

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?



Офлайн

#2 Ноя. 1, 2010 22:02:40

regall
От: Киев
Зарегистрирован: 2008-07-17
Сообщения: 1583
Репутация: +  3  -
Профиль   Отправить e-mail  

ORM выборка с учетом значений в нескольких строках

По идее так:

from django.db.models import Max
result = AllElements.objects.all().aggregate(Max('elem_value'))



Отредактировано (Ноя. 1, 2010 22:20:33)

Офлайн

#3 Ноя. 2, 2010 12:49:33

well
От:
Зарегистрирован: 2006-11-20
Сообщения: 163
Репутация: +  0  -
Профиль   Отправить e-mail  

ORM выборка с учетом значений в нескольких строках

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



Отредактировано (Ноя. 2, 2010 14:04:21)

Офлайн

#4 Ноя. 3, 2010 12:47:51

svas
От:
Зарегистрирован: 2010-01-27
Сообщения: 239
Репутация: +  9  -
Профиль   Отправить e-mail  

ORM выборка с учетом значений в нескольких строках

Попробуйте так

AllElements.objects.values('elem_name').annotate(max_elem_value=Max('elem_value'))



Офлайн

#5 Ноя. 3, 2010 17:20:49

well
От:
Зарегистрирован: 2006-11-20
Сообщения: 163
Репутация: +  0  -
Профиль   Отправить e-mail  

ORM выборка с учетом значений в нескольких строках

svas
Попробуйте так
AllElements.objects.values('elem_name').annotate(max_elem_value=Max('elem_value'))
Тут запрос будет проводить группировку по паре elem_name и elem_value, следовательно я получу одинаковые elem_name, если у них будут разные elem_value



Офлайн

#6 Ноя. 3, 2010 18:03:43

razum2um
От:
Зарегистрирован: 2009-03-20
Сообщения: 20
Репутация: +  0  -
Профиль   Отправить e-mail  

ORM выборка с учетом значений в нескольких строках

по моему я вас огорчу. была та же задача.
http://stackoverflow.com/questions/3508818/django-how-do-i-explicitly-make-a-query-with-a-having-clause
алсо сделал rawsql



Офлайн

#7 Ноя. 5, 2010 13:11:27

svas
От:
Зарегистрирован: 2010-01-27
Сообщения: 239
Репутация: +  9  -
Профиль   Отправить e-mail  

ORM выборка с учетом значений в нескольких строках

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.
Не знаю почему вы решили что будет проводится группировка по паре. Сам не пробовал, но судя по документации должно работать.



Офлайн

#8 Ноя. 5, 2010 22:07:44

well
От:
Зарегистрирован: 2006-11-20
Сообщения: 163
Репутация: +  0  -
Профиль   Отправить e-mail  

ORM выборка с учетом значений в нескольких строках

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. Хотя, там стоит немного другая задача, если я првильно понял тот запрос.



Отредактировано (Ноя. 5, 2010 22:11:36)

Офлайн

#9 Ноя. 7, 2010 12:53:27

svas
От:
Зарегистрирован: 2010-01-27
Сообщения: 239
Репутация: +  9  -
Профиль   Отправить e-mail  

ORM выборка с учетом значений в нескольких строках

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'}]
>>>
Может я не понимаю что вам действительно нужно?



Отредактировано (Ноя. 7, 2010 12:54:04)

Офлайн

#10 Ноя. 9, 2010 21:00:26

well
От:
Зарегистрирован: 2006-11-20
Сообщения: 163
Репутация: +  0  -
Профиль   Отправить e-mail  

ORM выборка с учетом значений в нескольких строках

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')
Еще раз простите за невнимательность и спасибо за настойчивость!



Отредактировано (Ноя. 10, 2010 23:07:59)

Офлайн

  • Начало
  • » Django
  • » ORM выборка с учетом значений в нескольких строках[RSS Feed]

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version