重叠预订SQL

时间:2018-07-16 11:50:54

标签: mysql overlapping

我的sql语句类似这里的问题Room Booking Query

如果一间公寓只有一个预订,则以下查询有效。但是如果一间公寓有多个预订,那么即使在请求的时间段内无法使用,也会出现此公寓。

SELECT DISTINCT `apartment`.*
FROM `apartment` `apartment`
LEFT JOIN `booking` `booking` ON `apartment`.`uid` = `booking`.`apartment`
WHERE (
    NOT(
        ( `booking`.`start` <= '2018-07-23')
        AND
        ( `booking`.`end` >= '2018-07-21')
    )
)

有人可以帮我写正确的sql吗?

更新: 根据马特·雷恩斯(Matt Raines)的提示,我在预订表上添加了带有公寓uid的野外公寓。我非常感谢您的任何建议,这些建议可以帮助我编写正确的SQL语句!

此处已更新演示数据:

--
-- Table structure for table `apartment`
--
CREATE TABLE `apartment` (
  `uid` int(11) NOT NULL,
  `title` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
  `bookings` int(10) UNSIGNED NOT NULL DEFAULT '0'
)
--
-- Data for table `tx_apartments_domain_model_apartment`
--
INSERT INTO `apartment` (`uid`, `title`, `bookings`) VALUES
(1, 'Apartment 1', 2),
(2, 'Apartment 2', 1),
(3, 'Apartment 3', 1),
(4, 'Apartment 4', 1);

--
-- Table structure for table `booking`
--
CREATE TABLE `booking` (
  `uid` int(11) NOT NULL,
  `start` date DEFAULT '0000-00-00',
  `end` date DEFAULT '0000-00-00',
  `apartment` int(10) UNSIGNED NOT NULL DEFAULT '0'
)
--
-- Data for table `booking`
--
INSERT INTO `booking` (`uid`, `start`, `end`, `apartment`) VALUES
(1, '2018-07-18', '2018-07-20', 1),
(2, '2018-07-21', '2018-07-23', 1),
(3, '2018-07-18', '2018-07-20', 2);

2 个答案:

答案 0 :(得分:0)

您偏离轨道认为这与联接中的多行有关。问题在于您在WHERE子句中的逻辑。您没有说出您想要的日期,所以不可能知道解决方案是什么。

我简化为仅查看预订表。我得到两行,您只希望其中一行。您所需要做的就是弄清楚您真正想要的条件。

mysql> SELECT * FROM booking WHERE NOT(start <= '2018-07-23' AND end >= '2018-07-21');
+-----+------------+------------+-----------+
| uid | start      | end        | apartment |
+-----+------------+------------+-----------+
|   1 | 2018-07-18 | 2018-07-20 |         1 |
|   3 | 2018-07-18 | 2018-07-20 |         2 |
+-----+------------+------------+-----------+
2 rows in set (0.00 sec)

答案 1 :(得分:0)

我认为您正在寻找在相关日期范围内没有任何预订的公寓清单。

相反,您的查询将查找在相关日期范围内至少个预订的公寓。

the question you have linked to的答案应该可以解决,但您也可以尝试反转问题以查找在该日期范围内预订的公寓。然后使用LEFT JOINWHERE booking.uid IS NULL过滤掉那些结果。

SELECT apartment.*
FROM apartment
LEFT JOIN booking ON apartment.uid = booking.apartment
                  AND booking.start <= '2018-07-23' AND booking.end >= '2018-07-21'
WHERE booking.uid IS NULL

您可能还想研究为该booking.apartment字段添加外键。至少,它的数据类型应该与apartment.uid相同(当前一个是INT(10)UNSIGNED,另一个是INT(11))。

除非您可以进行没有日期的预订,否则预订的startend日期可能应该为NOT NULL。并且apartment.bookings字段现在看起来很多余。