LINUX.ORG.RU

Опмитизация запроса максимальной цены за месяц

 , ,


0

1

Как это можно оптимизировать? Берем минимальную и максимальную дату и выбираем минимальный и максимальный год далее генерим года и месяцы, и выбираем максимальную цену в каждом месяце. Как это можно на орме сделать оптимальней? Т.е в конце концов мне нужно

{
  "2019": [
    {
      "month": 1,
      "cost": 12.0
    },
    {
      "month": 2,
      "cost": 14.2
    },
}

res = {}
min_year = Some.objects.values('timestamp').order_by('timestamp').first()['timestamp'].year
max_year = Some.objects.values('timestamp').order_by('timestamp').last()['timestamp'].year
for year in range(min_year, max_year + 1):
    for month in range(1, 13):
        qs = Some.objects.filter(
            timestamp__year=year,
            timestamp__month=month,
            name=param['name']
        ).aggregate(Max('cost'))['cost__max']
        if qs is not None:
            if year not in res:
                res[year] = []
                res[year].append({'month': month, 'cost': qs})

Ответ на: комментарий от dimuska139

Не ври, в новых джангах ничего такого не принято.

А вот что принято, так это модели лепить таким образом, чтобы не приходилось играть в датасайнс.
Тут одно из двух: или эти данные нужны часто и тогда нужно их кэшировать, а не вычислять заново каждый раз; или не нужны, но тогда и разницы никакой.

Goury ★★★★★ ()
Последнее исправление: Goury (всего исправлений: 1)

Вместо aggregate использовать annotate, сгруппировав по месяц-год. Что-то типа:

Some.objects.values(month, year).annotate(cost__max=Max('cost'))

Итого получается всего 1 запрос.

dicos ()
Ответ на: комментарий от crutch_master

Тру стори. Я недавно довольно тривиальный запрос на Gino полдня пытался нормально написпть, чтобы не нагибать БД, в итоге лишний джоин остался, ибо не было возможности извлечь объект из подзапроса. БД я таки нагнул.

Из плюсов — мне дали новый сервер помощнее. А потом я частично выбросил ORM и ещё немного заоптимизировал логику, в итоге летает.

WitcherGeralt ★★ ()