Поиск максимального количества предметов за раз в Django - PullRequest
3 голосов
/ 03 марта 2020

Я пытаюсь Django на своем бэкэнде, и в настоящее время у меня есть схема базы данных резервирования, похожая на следующую:

| Equipment id | Amount |   Starting time   |    Ending time
|      1       |   2    |  2021-09-21 12:30 | 2021-09-21 16:00
|      1       |   3    |  2021-09-21 15:00 | 2021-09-21 20:00
|      1       |   5    |  2021-09-21 18:00 | 2021-09-21 20:00

1)
Я должен был бы рассчитать сумму максимальное количество оборудования, зарезервированное в определенном временном окне, например, 17: 00-21: 00 должно вернуть 8. Я попытался использовать queryset.annotate(maxAmount=Sum(amount)), но в этом случае он возвращает сумму всего оборудования, зарезервированного в наборе запросов.

Может ли быть возможным решение сгруппировать резервирования с перекрывающимся временем windows, а затем узнать наибольшую сумму из этого? Какой может быть команда сгруппировать их таким образом?

2)
Вроде той же проблемы, но мне также нужно было бы найти время windows, где количество зарезервированного оборудования меньше определенного порог.

Пример с вышеприведенными данными: я бы хотел найти время, когда количество зарезервированного оборудования меньше 3: оно должно возвращать 00:00 -> 12:30, 16:00 -> 18:00 и 20 : 00 -> 00: 00.

РЕДАКТИРОВАТЬ: код, который я использую для генерации набора запросов:

def reservation_queryset(equipment_ids, starting_time, ending_time, time_between_res=0, id_to_ignore=None):
    '''Queryset for returning matching reservations, for reservation checks'''

    ### Get reservations that are ongoing at the time with time windows at ends
    # Reservations that start before this ends


    timequery = Q(starting_time__lt=ending_time + timedelta(minutes=time_between_res))


    # Reservations that end after this starts
    timequery.add(Q(ending_time__gt=starting_time - timedelta(minutes=time_between_res)), Q.AND)

    # Exclude the given reservation
    equipmentquery = ~Q(id=id_to_ignore)

    # Select the reservation equipments
    equipmentquery.add(Q(equipments__equipment__in=equipment_ids), Q.AND)

    # Combine the queries
    fullquery = timequery
    fullquery.add(equipmentquery, Q.AND)

    # Apply the filter as distinct and get the queryset
    existing_reservations = models.Reservation.objects.filter(fullquery).distinct()

    return existing_reservations

РЕДАКТИРОВАТЬ # 2: И вот код, который я в настоящее время использовал, чтобы найти максимальное количество оборудования:

def get_reserved_equipments(queryset):
    '''Returns a object with amounts of reserved equipments in the given queryset.'''

    values = queryset.prefetch_related('equipments').values('equipments__equipment')
    reserved_equipments = values.annotate(amount=Sum('equipments__amount'))
    return reserved_equipments```

1 Ответ

0 голосов
/ 05 марта 2020

Мне нужно было бы рассчитать количество максимального оборудования, зарезервированного в определенном временном окне.

Я думаю, аннотировать с помощью фильтра - это то, что вам нужно

from django.db.models import Sum, Q

qs_with_annotate = queryset.values('filed_with_equipment_id').annotate(amount_sum_17_21=Sum('amount', filter=Q(starting_time__hour__gte = 17) & Q(ending_time__hour__lt = 21))

после этого вы можете агрегировать Max

from django.db.models import Max

max_sum = qs_with_annotate.aggregate(max_sum = Max('amount_sum_17_21'))['max_sum']

и фильтровать, чтобы получить max filed_with_equipment_id

qs_with_annotate.filter(amount_sum_17_21 = max_sum)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...