MySQL日期范围内的天数,一个月内(预订表)

时间:2012-05-10 05:53:24

标签: mysql date datediff

我正在尝试使用以下信息为住宿服务创建报告:

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

分解为一年中的每个月。

限制 - 我目前正在使用PHP / MySQL创建此报告。 我将数据从预订系统中拉出一个月,然后使用ETL过程将其放入MySQL中。
因此,当预订在本月末分割时,我会有重复的记录。 (例如,下面的BookingID = 9216 - 这是因为出于收入目的,我们需要将收入的百分比分成相应的月份。)

问题。

如何编写一些SQL: 计算在某个房产中预订的房晚数,并按月计算。考虑到如果预订跨越月末,那个同一个月内的房间晚上,就像登记计算到那个月,和同一个月结账的房晚在同一个月作为结账。

起初我用过这个:DATEDIFF(Checkout,Checkin)。 但这导致一个月在31个月内有48个房间的夜晚。 (因为a)它将1个预订计为11个晚上,即使它在2个月内分开,并且b)因为它出现了两次)。

然后,一旦我有了声明,我需要将它整合回我的CrossTab SQL一整年。

我找到的一些资源,但似乎无法开展工作(MySql Query- Date Range within a Date Range& php mysql double date range

以下是表格样本:(有大约100,000行类似数据)。

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);

1 个答案:

答案 0 :(得分: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上查看。