2012-05-10 2 views
2

Я пытаюсь создать отчет для размещения службы со следующей информацией:MySQL Количество дней внутри DateRange, внутри месяца (бронирование Table)

Number of Bookings (Easy, use the COUNT function) 
Revenue Amount (Kind of easy). 
Number of Room nights. (Rather Hard it seems) 

разбивается на каждый месяц года ,

Ограничения. В настоящее время я использую PHP/MySQL для создания этого отчета. Я вынимаю данные из системы бронирования 1 месяц за раз, а затем используя ETL-процесс, чтобы поместить его в MySQL.
Из-за этого у меня есть дубликаты записей, когда бронирование разбивается в конце месяца. (например, BookingID = 9216 ниже - это потому, что для целей Дохода мы должны разделить процент дохода в соответствующий месяц).

Вопрос.

Как написать некоторый SQL, который будет: Рассчитайте количество ночей в номере, которые были забронированы в Недвижимость, и Группируйте их по месяцам. Принимая во внимание, что, если бронирование охватывает в конце месяца, то номера ночи, которые находятся внутри того же месяца, так как проверка учитывается в этом месяце и ночей в номере, которые в тот же месяц, что и выписка в тот же месяц как выписка.

Сначала я использовал это: DATEDIFF (Checkout, Checkin). Но это приводит к месяцу, имеющему 48 комнат ночи в 31-дневном месяце. (потому что а) он подсчитал 1 заказ на 11 ночей, даже через это было разделено на 2 месяца, и б), потому что он появляется дважды).

Затем, когда у меня есть инструкция, мне нужно интегрировать его обратно в свой CrossTab SQL в течение всего года.

Некоторые ресурсы, которые я нашел, но не могу показаться, чтобы сделать работу (MySql Query- Date Range within a Date Range & php mysql double date range)

Вот пример такой таблицы: (Есть ~ 100000 строк подобных данных).

CREATE TABLE IF NOT EXISTS `bookingdata` (
`idBookingData` int(11) NOT NULL AUTO_INCREMENT, 
`PropertyID` int(10) NOT NULL, 
`Checkin` date DEFAULT NULL, 
`Checkout` date DEFAULT NULL, 
`Rent` decimal(10,2) DEFAULT NULL, 
`BookingID` int(11) DEFAULT NULL, 
PRIMARY KEY (`idBookingData`), 
UNIQUE KEY `idBookingData_UNIQUE` (`idBookingData`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=10472 ; 

INSERT INTO `bookingdata` (`idBookingData`, `PropertyID`, `Checkin`, `Checkout`, `Rent`, `BookingID`) VALUES 
(5148, 2, '2011-07-02', '2011-07-05', 1105.00, 10612), 
(5149, 2, '2011-07-05', '2011-07-13', 2155.00, 10184), 
(5151, 2, '2011-07-14', '2011-07-17', 1105.00, 11102), 
(5153, 2, '2011-07-22', '2011-07-24', 930.00, 14256), 
(5154, 2, '2011-07-24', '2011-08-04', 1832.73, 9216), 
(5907, 2, '2011-07-24', '2011-08-04', 687.27, 9216), 
(5910, 2, '2011-08-11', '2011-08-14', 1140.00, 13633), 
(5911, 2, '2011-08-15', '2011-08-16', 380.00, 17770), 
(5915, 2, '2011-08-25', '2011-08-29', 1350.00, 17719), 
(5916, 2, '2011-08-30', '2011-09-01', 740.00, 16813); 

ответ

3

Вы находитесь на правильных линиях. Вы должны присоединиться запрос с таблицей несколько месяцев, для которого вы хотите получить данные, которые могут быть либо постоянными или (как показано в моем примере ниже) создаются динамически в UNION подзапроса:

SELECT YEAR(month.d), 
     MONTHNAME(month.d), 
     SUM(1 + DATEDIFF(-- add 1 because start&finish on same day is still 1 day 
      LEAST(Checkout, LAST_DAY(month.d)), GREATEST(Checkin, month.d) 
     )) AS days 
FROM  bookingdata 
    RIGHT JOIN (
        SELECT 20110101 AS d 
     UNION ALL SELECT 20110201 UNION ALL SELECT 20110301 
     UNION ALL SELECT 20110401 UNION ALL SELECT 20110501 
     UNION ALL SELECT 20110601 UNION ALL SELECT 20110701 
     UNION ALL SELECT 20110801 UNION ALL SELECT 20110901 
     UNION ALL SELECT 20111001 UNION ALL SELECT 20111101 
     UNION ALL SELECT 20111201 
) AS month ON 
      Checkin <= LAST_DAY(month.d) 
     AND month.d <= Checkout 
GROUP BY month.d 

Посмотри на sqlfiddle ,

+0

Условие соединения может быть упрощено до: 'Checkin <= LAST_DAY (month.d) И month.d <= Checkout' –

+0

@ypercube: Хорошая точка. Обновлено. – eggyal

+0

Большое вам спасибо, это самое близкое, что у меня есть вся неделя. Поскольку у нас есть это действительно раздражающее удвоение строк, возможно ли, что он будет использовать какой-то SELECT DISTINCT на столбце OrderID или в столбце Checkin/CheckOut. Что происходит, так это то, что строка добавляется дважды. Так, например, в июле месяце 11 ноября бронирование с 2011-07-24 по 2011-08-04 Первые 7 дней бронирования в июле добавляются правильно, но дважды. Или мне нужно очищать данные в процессе ETL? (колонка «Аренда» используется для каждого месяца). – Charlie