2

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

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)。但这导致一个月在 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);
4

1 回答 1

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上查看。

于 2012-05-10T06:22:29.300 回答