背景/アプリケーション
賃貸可能なプロパティのテーブルとこれらのプロパティの予約のテーブルを含むMySQLデータベースがあります。提供された2つの日付の間に利用可能なプロパティを見つけるための検索機能もあります。検索時に、ユーザーは開始日、滞在したい日数、および最大+/-7日の日付の柔軟性を入力できます。予約は、別の予約が終了するのと同じ日に開始できます(パーティー1は朝に出発し、パーティー2は夕方に到着します)。
柔軟性機能を効率的に実装するのに苦労しています。
スキーマ
CREATE TABLE IF NOT EXISTS `property` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(60) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE IF NOT EXISTS `property_booking` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`property_id` bigint(20) DEFAULT NULL,
`name` varchar(60) COLLATE utf8_unicode_ci DEFAULT NULL,
`date_start` date DEFAULT NULL,
`date_end` date DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
サンプルデータ
INSERT INTO `property` (`name`)
VALUES ('Property 1'), ('Property 2'), ('Property 3');
INSERT INTO `property_booking` (`property_id`,`name`,`date_start`,`date_end`)
VALUES (1, 'Steve', '2011-03-01', '2011-03-08'),
(2, 'Bob', '2011-03-13', '2011-03-20'),
(3, 'Jim', '2011-03-16', '2011-03-23');
サンプルシナリオ
ユーザーは、2011年3月10日に滞在を開始し、7日間滞在し、+/-2日間の柔軟性があることを選択します。以下のデータとパラメータを視覚化した画像を編集しました。(赤:予約1、緑:予約2、ストライプ:予約3、青:日付範囲(2011-03-10、+7日および+/-2日の柔軟性))

期待される結果
プロパティ1 (日付範囲全体で利用可能な予約)
プロパティ3 (2011-03-08または2011-03-09から利用可能な予約)
現在の方法
私の現在のクエリは、次のように、検索可能な合計日付範囲内の7日間の日付範囲すべての重複をチェックします。
SELECT p.`id`, p.`name`
FROM `property` p
WHERE (NOT (EXISTS (SELECT p2.`name` FROM `property_booking` p2 WHERE (p2.`property_id` = p.`id` AND '2011-03-10' < DATE_SUB(p2.`date_end`, INTERVAL 1 DAY) AND '2011-03-17' > DATE_ADD(p2.`date_start`, INTERVAL 1 DAY)))))
OR (NOT (EXISTS (SELECT p3.`name` FROM `property_booking` p3 WHERE (p3.`property_id` = p.`id` AND '2011-03-11' < DATE_SUB(p3.`date_end`, INTERVAL 1 DAY) AND '2011-03-18' > DATE_ADD(p3.`date_start`, INTERVAL 1 DAY)))))
OR (NOT (EXISTS (SELECT p4.`name` FROM `property_booking` p4 WHERE (p4.`property_id` = p.`id` AND '2011-03-09' < DATE_SUB(p4.`date_end`, INTERVAL 1 DAY) AND '2011-03-16' > DATE_ADD(p4.`date_start`, INTERVAL 1 DAY)))))
OR (NOT (EXISTS (SELECT p5.`name` FROM `property_booking` p5 WHERE (p5.`property_id` = p.`id` AND '2011-03-12' < DATE_SUB(p5.`date_end`, INTERVAL 1 DAY) AND '2011-03-19' > DATE_ADD(p5.`date_start`, INTERVAL 1 DAY)))))
OR (NOT (EXISTS (SELECT p6.`name` FROM `property_booking` p6 WHERE (p6.`property_id` = p.`id` AND '2011-03-08' < DATE_SUB(p6.`date_end`, INTERVAL 1 DAY) AND '2011-03-15' > DATE_ADD(p6.`date_start`, INTERVAL 1 DAY)))));
サンプルデータセットでは、かなり高速ですが、はるかに大きなデータセットでは、かなり遅くなります。完全な+/-7日間の柔軟性を構築するとさらに遅くなります。
このクエリをより適切に作成する方法について誰かが何か提案がありますか?