2013-07-07 2 views
3

У меня есть таблица магазинов транспортных средства резервирование для каждой записи я имею dateFrom «дату начала бронирования» и «дату конца бронирования» dateToКак рассчитать общее количество дней для резервирования в MySQL

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

Бизнес правило являются являются следующие

  1. , если dateFrom и dateTo в тот же день, то, что считается 1 дней
  2. Если заказ от 2013-05-25 до 2013-06-06 затем за 7 дней пойти в мае месяце и 5 дней идут в июне месяце вот ломаются этой логики
2013-05-25 - 2013-05-26 (May) 
2013-05-26 - 2013-05-27 (May) 
2013-05-27 - 2013-05-28 (May) 
2013-05-28 - 2013-05-29 (May) 
2013-05-29 - 2013-05-30 (May) 
2013-05-30 - 2013-05-31 (May) 
2013-05-31 - 2013-06-01 (**May**) 
2013-06-01 - 2013-06-02 (June) 
2013-06-02 - 2013-06-02 (June) 
2013-06-03 - 2013-06-02 (June) 
2013-06-04 - 2013-06-02 (June) 
2013-06-05 - 2013-06-02 (June) 

Это пример того, как расчет должен работать.

Для дохода Я полагаю, чтобы вычислить среднесуточную арендную плату пути деления общей выручки от общего объема арендуемых дней, а затем умножив средний дневной на общий день, что соответствует этому диапазону

Это мой текущий запрос, но не правильно вычисляет сегодняшние дни. поэтому в приведенном выше примере, если мы предположим, что общий доход за весь ресервировании $ 1500 то средняя суточная арендная $1500/12 = $125

так, так как диапазон, который мы вычисляем является "2013-06-01 00:00:00" к "2013-06-16 23:59:59", то это транспортное средство должно отображаться общее дней 5, а общий доход - 625 долларов. Более того, если диапазон был 2013-05-01 00:00:00 в 2013-05-31 23:59:59 то же транспортное средство будет иметь в общей сложности 7 дней и общий доход в размере $ 875

Ниже приведен мой текущий запрос в том, где я пытаюсь вычислить разницу.

SELECT rs.vehicle_id, 
    ROUND(SUM(


     CASE 
     WHEN (rs.dateFrom BETWEEN "2013-06-01 00:00:00" AND "2013-06-16 23:59:59") 
     AND (rs.dateTo BETWEEN "2013-06-01 00:00:00" AND "2013-06-16 23:59:59") 
     THEN (rs.totalRent + rs.totalTax) 

     WHEN rs.dateTo BETWEEN "2013-06-01 00:00:00" AND "2013-06-16 23:59:59" 
     AND rs.dateFrom < "2013-06-01 00:00:00" 
     THEN (((rs.totalRent + rs.totalTax)/CASE WHEN DATEDIFF(rs.dateTo,rs.dateFrom) = 0 THEN 1 ELSE DATEDIFF(rs.dateTo,rs.dateFrom) END) * (DATEDIFF(rs.dateTo, "2013-06-01 00:00:00"))) 

     WHEN rs.dateFrom BETWEEN "2013-06-01 00:00:00" AND "2013-06-16 23:59:59" 
     AND rs.dateTo > "2013-06-16 23:59:59" 
     THEN (((rs.totalRent + rs.totalTax)/CASE WHEN DATEDIFF(rs.dateTo,rs.dateFrom) = 0 THEN 1 ELSE DATEDIFF(rs.dateTo,rs.dateFrom) END) * (DATEDIFF("2013-06-16 23:59:59",rs.dateFrom)+1)) 

     WHEN rs.dateFrom < "2013-06-01 00:00:00" AND rs.dateTo > "2013-06-16 23:59:59" 
     THEN (((rs.totalRent + rs.totalTax)/CASE WHEN DATEDIFF(rs.dateTo,rs.dateFrom) = 0 THEN 1 ELSE DATEDIFF(rs.dateTo,rs.dateFrom) END) * (DATEDIFF("2013-06-16 23:59:59", "2013-06-01 00:00:00") +1)) 

     ELSE 0 END 

)) AS income, 


SUM(

     CASE 
     WHEN (rs.dateFrom BETWEEN "2013-06-01 00:00:00" AND "2013-06-16 23:59:59") 
     AND (rs.dateTo BETWEEN "2013-06-01 00:00:00" AND "2013-06-16 23:59:59") 
     THEN CASE WHEN DATEDIFF(rs.dateTo,rs.dateFrom) = 0 THEN 1 ELSE DATEDIFF(rs.dateTo,rs.dateFrom) END 

     WHEN rs.dateTo BETWEEN "2013-06-01 00:00:00" AND "2013-06-16 23:59:59" 
     AND rs.dateFrom < "2013-06-01 00:00:00" 
     THEN CASE WHEN DATEDIFF(rs.dateTo, "2013-06-01 00:00:00") = 0 THEN 1 ELSE (DATEDIFF(rs.dateTo, "2013-06-01 00:00:00")) END 

     WHEN rs.dateFrom BETWEEN "2013-06-01 00:00:00" AND "2013-06-16 23:59:59" 
     AND rs.dateTo > "2013-06-16 23:59:59" 
     THEN CASE WHEN DATEDIFF("2013-06-16 23:59:59",rs.dateFrom) = 0 THEN 1 ELSE (DATEDIFF("2013-06-16 23:59:59",rs.dateFrom)) END 

     WHEN rs.dateFrom < "2013-06-01 00:00:00" AND rs.dateTo > "2013-06-16 23:59:59" 
     THEN DATEDIFF("2013-06-16 23:59:59", "2013-06-01 00:00:00")+1 

     ELSE 0 END 

) AS days  
FROM reservation AS rs 
WHERE rs.reservationStatus IN (2,3) 
GROUP BY rs.Vehicle_id 

Проблема заключается в том, что запрос не вычисляет полные дни правильно. Может ли кто-нибудь помочь мне с этим, пожалуйста?

Ниже приведен пример моего кода

http://sqlfiddle.com/#!2/f6cbc/3 для тестирования с данными

+0

Вы ищете одно число, месячную арендную плату за конкретный автомобиль в течение определенного месяца или несколько номеров, арендную плату за месяц, за конкретный автомобиль? –

+0

Номер на автомобиль за весь диапазон. поэтому для транспортного средства №1 мне нужны полные зарезервированные дни в выбранном диапазоне и для тех же автомобилей общий доход. поэтому, если у меня всего 10 автомобилей, тогда я должен получить в общей сложности 10 записей. – Jaylen

+0

. Я принимаю удар, но я все еще испытываю трудности с визуализацией проблемы, которую вы описываете. Вы обсудили несколько вопросов, разделив арендную плату в период с мая по июнь, подсчитав количество дней, подсчитав ренту/налог за диапазон дат, основанный на средней ренте/налоге. Не могли бы вы разместить некоторые данные и точно, что вы ожидаете увидеть от этих данных? В идеале вы бы создали таблицу в sqlFiddle.com –

ответ

1

Там не перекрываются в интервалах (т.е. для автомобиля у вас есть какая-то логика, чтобы убедиться, что она не резервируется несколько раз?

Если вы ищете всю историю, можно, конечно, просто суммировать invidual длину каждой оговорки. вы хотите, чтобы некоторые за месяц разбивки?

SELECT SUM(TO_DAYS(dateTo)-TO_DAYS(dateFrom) +1) AS sum_days_reserved FROM table 
+0

Как это поможет мне рассчитать общие дни на основе бизнес-правил? – Jaylen

1

Так что я сделал удар. Начнем с кода. Объяснение приходит позже.

SELECT rs.vehicle_id, 
    round(sum(datediff(least(rs.dateTo, '2013-06-02 00:00:00'), 
       greatest(rs.dateFrom, '2013-05-31 00:00:00'))*(totalRent + totalTax)*datediff(least(rs.dateTo, '2013-06-02 00:00:00'), 
       greatest(rs.dateFrom, '2013-05-31 00:00:00'))/totalDays)) 
     AS income, 
    sum(datediff(least(rs.dateTo, '2013-06-02 00:00:00'), 
       greatest(rs.dateFrom, '2013-05-31 00:00:00'))) 
     AS days 
FROM reservation rs 
    WHERE rs.dateFrom < '2013-06-02 00:00:00' 
    AND rs.dateTo > '2013-05-31 00:00:00' 
GROUP BY rs.vehicle_id; 

SQL Fiddle

Самое главное, что вы должны думать о том, является ли это включено или эксклюзивный диапазон дат. Итак, если вы хотите получить сумму от 5/31 до 6/1, означает ли это, что вы хотите включить доход от 6/1, или это означает, что вы ищете доход только на 5/31. Эта концепция привлекает множество разработчиков. Из ваших комментариев и сообщений я предполагаю, что вы хотите, чтобы диапазон дат был исключительным.

В том случае, когда я создал, окно начинается с 5/31 в 00:00:00 до 6/1 в 00:00. Если вы хотите, чтобы это было включено, вы могли бы закончить окно в 6/2 00:00:00.

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

Тогда вы можете рассчитать фактическое количество дней в окне, просмотрев максимум даты с окна и окна, а также минимум даты Date и WindowEnd.

+0

Спасибо за ваше время. Для дохода это должна быть средняя арендная плата * количество дней. Если вы измените диапазон своего решения на 2013-06-01 00:00:00 до 2013-06-01 23:59:59, тогда вы получите 0 дней и за доход. также, если я отдыхаю с 2013-05-01 00: 0: 00 до 2013-06-28 00:00:00, эта запись будет проигнорирована. – Jaylen

+0

Я уточнил свой ответ. Ты прав. В течение одного дня он всегда должен перейти в 00:00:00 следующего дня, так что всегда должен быть ваш конечный результат. Вы никогда не должны использовать 23:59:59. Он выбирает оговорку, о которой вы упоминали, и я ввел ее в новый SQLFiddle –

+0

, если дата будет создана из datetimepicker.если пользователь выбирает диапазон дат с 2013-06-01 по 2013-06-30, тогда вам нужно сообщать о каждом дне с 2013-06-02 по 2013-06-30, если дата бронирования меньше 2013-06- 01, но если datefrom = = 2013-06-01, то отчет от 2013-06-01. то же самое на дату окончания. если dateTo составляет <= 2013-06-30, тогда отчитываться до 2013-06-30, но если дата больше, чем 2013-06-30, то сообщите до 2013-07-01. Надеюсь, у меня есть смысл, потому что он очень востребован. – Jaylen

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