Sql 在预订系统中寻找免费的位置

Sql 在预订系统中寻找免费的位置,sql,mysql,django,date,Sql,Mysql,Django,Date,在年,我试图简化问题,但无意中提出了一个不同且更简单的问题 与其用编辑使问题复杂化,我要问我真正想问的问题 我有两张桌子,一张是酒店的,另一张是预订的。预订具有属性的外键以及开始和结束日期 用户正在搜索可用插槽并提供所需的持续时间(以天为单位)。他们还提供了一系列他们感兴趣的开始日期。因此,搜索将沿着以下路线进行: “找到我所有的财产我想要一个3天的时间段,从5月份开始。” 现在,我可以通过以下方式实现这一点: 1.为每个潜在的开始日运行31个查询 2.查找5月份的所有预订,将它们压缩成一个包含

在年,我试图简化问题,但无意中提出了一个不同且更简单的问题

与其用编辑使问题复杂化,我要问我真正想问的问题

我有两张桌子,一张是酒店的,另一张是预订的。预订具有属性的外键以及开始和结束日期

用户正在搜索可用插槽并提供所需的持续时间(以天为单位)。他们还提供了一系列他们感兴趣的开始日期。因此,搜索将沿着以下路线进行: “找到我所有的财产我想要一个3天的时间段,从5月份开始。”

现在,我可以通过以下方式实现这一点: 1.为每个潜在的开始日运行31个查询 2.查找5月份的所有预订,将它们压缩成一个包含31个布尔值的数组,表示天数,并循环查找插槽

我认为(2)在大多数情况下更有效。有更好的算法吗?是否有一个纯SQL解决方案


我将使用Django,而且我的数据集很小,所以我可能可以使用“哑”方法,但我很想知道最好的算法是什么样的

对于您的应用程序来说,可能是杀伤力过大-但是:

一个相对简单的改进搜索的方法是改变预订表,使其成为一个“可用性”表,而不是使“写入”过程更加复杂

添加一个布尔列以指示插槽是空闲的还是已预订的(最好还是输入已预订的客户的id,如果插槽是空闲的,则使用0)

从2009年1月1日->20年12月31日的一个空闲时段开始

当您预订时,将免费时段分为3个(两个插入和一个更新),即预订的时段和两个可用的时段

继续这样做,随着时间框架变得越来越零散,预订流程将包括以下内容之一:

  • 将整个“可用插槽”分配给某人(一次更新)
  • 将“可用插槽”拆分为两个(一个更新和一个插入)
  • 如果有人从可用插槽中预订中间部分,则将插槽拆分为3(如上所述)
管理起来并不复杂,搜索过程变成了一个简单的查询:查找所需时间范围内可用的任何时段(booked=false或customerid=0,无论您选择哪种方式),其中enddate-startdate>=您想要的天数


它将booking/availability表的大小增加了一倍,并使预订变得不那么简单,但取舍是搜索过程几乎和它得到的一样简单。

对于您的应用程序来说,可能有点过头了-但是:

一个相对简单的改进搜索的方法是改变预订表,使其成为一个“可用性”表,而不是使“写入”过程更加复杂

添加一个布尔列以指示插槽是空闲的还是已预订的(最好还是输入已预订的客户的id,如果插槽是空闲的,则使用0)

从2009年1月1日->20年12月31日的一个空闲时段开始

当您预订时,将免费时段分为3个(两个插入和一个更新),即预订的时段和两个可用的时段

继续这样做,随着时间框架变得越来越零散,预订流程将包括以下内容之一:

  • 将整个“可用插槽”分配给某人(一次更新)
  • 将“可用插槽”拆分为两个(一个更新和一个插入)
  • 如果有人从可用插槽中预订中间部分,则将插槽拆分为3(如上所述)
管理起来并不复杂,搜索过程变成了一个简单的查询:查找所需时间范围内可用的任何时段(booked=false或customerid=0,无论您选择哪种方式),其中enddate-startdate>=您想要的天数


它将booking/availability表的大小增加了一倍,并使预订变得不那么简单,但取舍是搜索过程几乎和它得到的一样简单。

表定义可能会有所帮助,但现在开始。这应该适用于MS SQL Server,但一旦您理解了其背后的思想,将其转换为MySQL应该是一项简单的任务

日历表只是一个标准实用程序表,其中包含数据库中有用的所有日期。如果您还没有,我建议您创建一个并填充它

CREATE TABLE Calendar
(
     date        DATETIME     NOT NULL,
     is_holiday  BIT          NOT NULL,
     -- any other columns that might be relevant for your business
     CONSTRAINT PK_Calendar PRIMARY KEY CLUSTERED (date)
)
然后,您需要在表中填入对您的业务可能有意义的任何日期。即使追溯到100年,再向前追溯100年,表中的行数仍然不到75K行,并且它是在日期上聚集的,因此它应该是快速且易于处理的。它使许多基于日期的查询变得更加简单

SELECT
     P.property_id,
     C.date
FROM
     Calendar C
JOIN Properties P ON 1=1
WHERE
     C.date BETWEEN @search_start_date AND @search_end_date AND
     NOT EXISTS
     (
          SELECT
               *
          FROM
               Bookings B
          WHERE
               B.property_id = P.property_id AND
               B.start_date <= DATEADD(dy, @slot_length, C.date) AND  -- You would use MySQLs date function
               B.end_date   >= C.date
     )
选择
P.property_id,
C.日期
从…起
日历C
在1=1时连接属性P
哪里
C.@search\u start\u date和@search\u end\u date之间的日期,以及
不存在
(
挑选
*
从…起
预订B
哪里
B.property\u id=P.property\u id和
B.开始日期=C.日期
)
或者:

SELECT
     P.property_id,
     C.date
FROM
     Calendar C
JOIN Properties P ON 1=1
LEFT OUTER JOIN Bookings B ON
               B.property_id = P.property_id AND
               B.start_date <= DATEADD(dy, @slot_length, C.date) AND  -- You would use MySQLs date function
               B.end_date   >= C.date
WHERE
     C.date BETWEEN @search_start_date AND @search_end_date AND
     B.booking_id IS NULL
选择
P.property_id,
C.日期
从…起
日历C
在1=1时连接属性P
左外连接预订B ON
B.property\u id=P.property\u id和
B.开始日期=C.日期
哪里
C.@search\u start\u date和@search\u end\u date之间的日期,以及
B.u id为空

表定义可能会有所帮助,但现在开始。这应该适用于MS SQL Server,但一旦您理解了其背后的思想,将其转换为MySQL应该是一项简单的任务

日历表只是一个标准实用程序表,其中包含数据库中有用的所有日期。如果您还没有,我建议您创建一个并填充它

CREATE TABLE Calendar
(
     date        DATETIME     NOT NULL,
     is_holiday  BIT          NOT NULL,
     -- any other columns that might be relevant for your business
     CONSTRAINT PK_Calendar PRIMARY KEY CLUSTERED (date)
)
然后,您需要在表中填入对您的业务可能有意义的任何日期。即使你回到100岁