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(チェックアウト、チェックイン)。しかし、それは 1 か月 31 日で 48 部屋の夜を過ごすことにつながります。(a) 1 回の予約が 2 か月に分割されていても 11 泊としてカウントされているため、および b) 2 回表示されているため)。

次に、ステートメントを取得したら、それを 1 年間 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 に答える