简体   繁体   English

如何确认房间是否已满?

[英]How to verify if room is fully booked?

I am currently working on a booking system . 我目前正在研究订票系统。 I'm currently encountering a problem in finding out if an apartment is fully booked. 我目前在查找公寓是否已满时遇到问题。 In my database i have a table holding all the apartments and their details. 在我的数据库中,我有一个表格,其中包含所有公寓及其详细信息。 I am trying to get the dates that all apartments for example with 4 bedrooms that are booked. 我正在尝试获取所有带有4间卧室的公寓的预定日期。 I am running the following sql to return the booked dates of all 4 bedroom apartments. 我正在运行以下sql以返回所有4间卧室公寓的预订日期。

SELECT * 
FROM  `apartment_booking` AS ab
JOIN apartment AS a ON ( a.id = apartmentId ) 
JOIN booking AS b ON ( b.id = bookingId ) 
WHERE bedrooms =  '4'
ORDER BY checkIn

The return of the sql is sql的返回是

id  CheckIn     checkOut     userId
74  2014-04-15  2014-04-22    1
75  2014-04-15  2014-04-22    1
102 2014-06-03  2014-07-07    1
71  2014-06-16  2014-06-23    1
114 2014-07-19  2014-08-02    1
121 2014-07-20  2014-08-02    1
57  2014-07-22  2014-08-05    1
122 2014-07-28  2014-08-02    1
117 2014-08-03  2014-08-10    1

As i have 4 apartments in the system with four bedrooms i would like to get the dates that all four bedrooms are booked. 因为我在系统中有4间公寓,其中有4间卧室,所以我想获得所有4间卧室都被预订的日期。

Example with the output got the dates 2014-07-28 till 2014-08-02 are fully booked as in that date range there are in total four bookings. 输出示例显示日期为2014-07-28到2014-08-02的书已被预订满,因为在该日期范围内,总共有四笔预订。

Database: 数据库:

CREATE TABLE `apartment` (
  `id` int(11) NOT NULL auto_increment,
  `code` varchar(4) NOT NULL,
  `bedrooms` int(11) NOT NULL,
  `description` varchar(500) default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=26 ;

--
-- Dumping data for table `apartment`
--

INSERT INTO `apartment` (`id`, `code`, `bedrooms`, `description`) VALUES
(1, '1c', 3, ''),
(4, '4d', 4, NULL),
(5, '5b', 2, NULL),
(10, '10c', 3, NULL),
(11, '11b', 2, NULL),
(12, '12d', 4, NULL),
(13, '13c', 3, NULL),
(14, '14a', 1, 'Yo'),
(15, '15b', 2, NULL),
(16, '16b', 2, NULL),
(17, '17d', 4, NULL),
(22, '22d', 4, NULL),


CREATE TABLE `apartment_booking` (
  `id` int(11) NOT NULL auto_increment,
  `apartmentId` int(11) NOT NULL,
  `bookingId` int(11) NOT NULL,
  `ref` varchar(50) NOT NULL,
  `pax` int(11) NOT NULL default '1',
  `remarks` varchar(500) default NULL,
  `guestFullName` varchar(30) default NULL,
  `guestCountry` varchar(2) default NULL,
  `guestFlightDetails` varchar(200) default NULL,
  PRIMARY KEY  (`id`),
  KEY `apartmentId` (`apartmentId`),
  KEY `bookingId` (`bookingId`),
  KEY `ref` (`ref`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=179 ;

--
-- Dumping data for table `apartment_booking`
--

INSERT INTO `apartment_booking` (`id`, `apartmentId`, `bookingId`, `ref`, `pax`, `remarks`, `guestFullName`, `guestCountry`, `guestFlightDetails`) VALUES
(164, 1, 140, 'Hotelbeds', 5, '', 'Andrew Robertson', 'MT', '')
(165, 21, 141, 'Hotelbeds', 6, '', 'Pipitone', 'MT', ''),
(166, 5, 142, 'maltaholidaylets', 2, '', 'holly turpin', 'MT', ''),
(167, 12, 143, 'direct003', 4, '', 'Bernard Walch', 'MT', ''),
(168, 17, 144, 'meetingpoint', 4, '', 'Edvin Modigh', 'MT', ''),
(169, 23, 145, 'direct', 3, '', 'Andrea bacchetti', 'MT', ''),
(172, 25, 148, 'direct', 5, '', 'Wimold Peters', 'MT', ''),
(173, 20, 149, '7228110687', 4, '', 'Ms. Benedetta Tombari', 'MT', ''),
(174, 23, 149, '7228110687 meetingpoint', 2, '', 'Ms. Milena Moretti', 'MT', ''),
(175, 25, 150, 'meetingpoint', 6, '', 'N Burdett', 'MT', ''),
(176, 8, 151, 'Hotelbeds', 2, '', 'tito titti', 'MT', ''),
(177, 1, 152, 'meetingpoint', 3, '', 'Stephen Mckenna', 'MT', ''),
(178, 16, 153, 'mhcs', 4, '', 'Wojclech Blaszak', 'MT', '');

-- --------------------------------------------------------

--
-- Table structure for table `booking`
--

CREATE TABLE `booking` (
  `id` int(11) NOT NULL auto_increment,
  `reference` varchar(20) NOT NULL,
  `dateTime` datetime NOT NULL,
  `checkIn` date NOT NULL,
  `checkOut` date NOT NULL,
  `userId` int(11) default NULL,
  PRIMARY KEY  (`id`),
  KEY `agent` (`userId`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=154 ;

--
-- Dumping data for table `booking`
--

INSERT INTO `booking` (`id`, `reference`, `dateTime`, `checkIn`, `checkOut`, `userId`) VALUES
(136, 'euroresort booking.b', '2014-07-02 09:30:08', '2014-08-04', '2014-08-11', 1),
(137, '7014505534', '2014-07-02 09:32:05', '2014-07-19', '2014-07-24', 1),
(138, 'BR4277518', '2014-07-02 09:45:02', '2014-08-09', '2014-08-16', 1),
(139, '100206154', '2014-07-02 10:11:45', '2014-07-27', '2014-08-03', 1),
(140, '120-135249-95', '2014-07-02 10:13:14', '2014-07-02', '2014-07-03', 1),
(141, '120-135181-94', '2014-07-02 10:14:31', '2014-08-10', '2014-08-17', 1),
(142, '000548MHL', '2014-07-02 12:38:54', '2014-08-25', '2014-09-01', 1),
(143, 'direct003', '2014-07-02 15:48:04', '2014-08-11', '2014-08-22', 1),
(144, 'SH3049361', '2014-07-02 15:52:18', '2014-08-05', '2014-08-14', 1),
(145, 'direct009', '2014-07-03 08:27:56', '2014-07-19', '2014-07-26', 1),
(148, 'direct010', '2014-07-04 08:12:13', '2014-07-08', '2014-07-22', 1),
(149, '7228110687', '2014-07-04 13:28:16', '2014-08-10', '2014-08-16', 1),
(150, '7308310623', '2014-07-07 08:39:04', '2014-08-11', '2014-08-20', 1),
(151, '120-135677-92', '2014-07-07 08:43:06', '2014-08-22', '2014-08-29', 1),
(152, '100209964', '2014-07-07 10:59:16', '2014-08-05', '2014-08-12', 1),
(153, 'mhcs', '2014-07-07 13:07:22', '2014-08-08', '2014-08-16', 1);

It gets a bit complicated. 它变得有点复杂。

The following query generates a range of numbers from 0 to 999, and adds each number as a number of days to the checkIn date for each booking, where the resulting date is less than or equal to the checkOut date for bookings for apartments with 4 rooms. 以下查询生成一个介于0到999之间的数字范围,并将每个数字作为天数添加到每个预订的入住日期中,其中得出的日期小于或等于四个房间的公寓的预订的退房日期。 This should give one row per apartment per day booked. 这应该使每间公寓每天预订一排。

The number of booking ids for each date is then counted, and compared with the number of apartments with 4 bedrooms (from a sub query). 然后计算每个日期的预订ID数量,并将其与4间卧室的公寓数量进行比较(来自子查询)。 The HAVING clause then discards all rows for dates where the number of aparments booked is not the same as the number of apartments with 4 rooms. 然后,HAVING子句会丢弃预订的公寓数量与4个房间的公寓数量不同的日期的所有行。

SELECT aBookedDate, sub2.apartment_cnt, COUNT(id) AS all_booking_cnt
FROM
(
    SELECT booking.id, DATE_ADD(booking.checkIn, INTERVAL iCnt DAY) AS aBookedDate
    FROM
    (
        SELECT units.i + tens.i * 10 + hundreds.i * 100 AS iCnt
        FROM (SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9)units
        CROSS JOIN (SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9)tens
        CROSS JOIN (SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9)hundreds
    ) sub0
    CROSS JOIN booking
    INNER JOIN apartment_booking ON booking.id = apartment_booking.bookingId
    INNER JOIN apartment ON apartment.id = apartment_booking.apartmentId
    WHERE DATE_ADD(booking.checkIn, INTERVAL iCnt DAY) <= booking.checkOut
    AND apartment.bedrooms = 4
) sub1
CROSS JOIN 
(
    SELECT COUNT(*) AS apartment_cnt
    FROM apartment 
    WHERE bedrooms = 4
) sub2
GROUP BY aBookedDate
HAVING all_booking_cnt = sub2.apartment_cnt

SQL fiddle for it:- SQL摆弄它:-

http://www.sqlfiddle.com/#!2/6edbe/5 http://www.sqlfiddle.com/#!2/6edbe/5

You need left outer join, so you also show the apartments that are not booked. 您需要左外部联接,因此您还要显示未预订的公寓。

SELECT * 
FROM  `apartment_booking` AS ab
JOIN apartment AS a ON ( a.id = apartmentId ) 
JOIN booking AS b ON ( b.id = bookingId ) 
WHERE bedrooms =  '4' and userId is null
ORDER BY checkIn

Ones that have null user id will be empty (aka non-booked), since there is no booking connected to that apartment. 用户ID为空的用户将为空(也就是未预订),因为没有预订与该公寓相关。 You didn't say enough about the structure so I take it you delete the bookings rather than keeping history. 您没有对结构进行足够的说明,所以我认为您是删除预订而不是保留历史记录。 If you keep all historical entries you need to check the date with today's date instead. 如果保留所有历史记录条目,则需要用今天的日期来检查日期。

SELECT * 
FROM  `apartment_booking` AS ab
JOIN apartment AS a ON ( a.id = apartmentId ) 
LEFT OUTER JOIN booking AS b ON ( b.id = bookingId ) 
WHERE bedrooms =  '4' and checkOut > NOW()
ORDER BY checkIn

EDIT: 编辑:

It should look something like, I'll try to prepare a fiddle with that later: 它看起来应该像这样,稍后我将尝试准备一个小提琴:

SELECT 
    (COUNT( 
        SELECT * 
        FROM  `apartment_booking` AS ab
        JOIN apartment AS a ON ( a.id = apartmentId ) 
        LEFT OUTER JOIN booking AS b ON ( b.id = bookingId ) 
        WHERE bedrooms =  '4' and checkIn <= <<<SOMEDATEHERE>>> and checkOut >= <<<<SOMEOTHERDATEHERE>>>>>
     ) >= 4);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM