2016-02-06 5 views
0

В настоящее время я работаю над веб-приложением для управления арендой устройств. У меня устройств, которые принадлежат к одному типуустройства и связанные с арендой с открывающей и закрывающей датой.Запрос на доступность аренды в течение дат

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

| Device Type: | 01.01 | 02.01 | 03.01 | 04.01 | 05.01 | 
-------------------------------------------------------- 
|Laptop  | 10 | 10 | 10 | 5 | 5 | 
|Mobile Phone | 30 | 25 | 25 | 10 | 10 | 

На данный момент я узнать доступные устройства для любой заданной даты следующим образом:

  1. Найдите прокат, которые пересекаются с датой
  2. Получить устройства, связанные с этими арендами
  3. всех устройств не доступны 2.

Соответствующий код выглядит следующим образом:

def Device.available_devices(start_date, end_date) 
    other_rentals = Rental.where("outbound_delivery_date <= ? AND inbound_delivery_date >= ?", end_date, start_date) 

    unavailable_devices = DeviceRental.where("rental_id IN (?)", other_rentals.map(&:id)) 

    if other_rentals.any? && unavailable_devices.any? 
     @available_devices = Device.where("NOT devices.id IN (?)", unavailable_devices.map(&:device_id)).joins(:device_type).order("device_types.name") 
    else 
     @available_devices = Device.all 
    end 
    end 

Теперь отображая это в таблице означает переход через 1.-3. для каждой даты и, следовательно, вызывает огромное количество запросов БД, которые кажутся неэффективными. Может ли кто-нибудь указать мне в правильном направлении, как я могу получить эти данные более эффективным способом?

ответ

0

Вы можете сделать это в одном запросе с помощью NOT IN

available_devices = Device.where('devices.id NOT IN (SELECT device_id FROM device_rentals WHERE rental_id IN (SELECT rentals.id from rentals WHERE outbound_delivery_date <= ? AND inbound_delivery_date >= ?))', end_date, start_date) 

, чтобы получить количество ...

available_devices.count 
+0

Я думаю, что из-за модели DeviceRental между ними на самом деле должно быть " available_devices = Device.where ('devices.id NOT IN (SELECT device_id FROM device_rentals WHERE rent_id IN (SELECT rentals.id из аренды WHERE outbound_delivery_date <=? AND inbound_delivery_date> =?))', end_date, start_date) ", но есть способ, которым я не должен запускать этот запрос один раз для каждого да te в диапазоне, для которого я хочу узнать о доступности? –

+0

О, одна аренда может охватывать несколько устройств? Я предполагаю, что это было много, а не HABTM. В любом случае, этот ответ приводит вас к одному запросу на элемент столбца, который (I tihink), скорее всего, лучший результат, который вы сможете получить. Если вы попытаетесь сделать несколько столбцов, будет ли возвращенный телефон принадлежать первому столбцу? Второй? Я не вижу, как разрешить это, не делая поиск по возвращенным записям для каждого столбца, который будет менее эффективным, чем запрос для каждого столбца. – SteveTurczyn

+0

Для этого варианта использования на самом деле мне просто нужно количество доступных устройств для каждого типа устройства на каждую дату. Теперь я использую вышеуказанный запрос, а затем присоединяюсь к типу устройства, группируя его по имени и подсчету. После этого прокрутите все типы устройств и получите счетчик из ранее созданного хэша и отобразите его в представлении. –

Смежные вопросы