预订系统的核心 - 有效地查找未预留的项目

Maw*_*awg 3 mysql

这似乎是一个常见问题,但我一直在网上搜索,找不到答案.

我想保留一些东西(没有偏天),所以我想我需要一个像这样的桌子:

CREATE TABLE reservations 
    (
     item int, 
     customer int, 
     startDate date, 
     endDate date
    );
Run Code Online (Sandbox Code Playgroud)

(嗯,我的主键是什么?item和startDate?我甚至需要PK吗?)

但我的主要问题是如何找到一个免费项目,给定一个开始和结束日期.我的SELECT ...样子是什么样的?

对于奖励分数,我们可以假设所有项目都是相同的,并且我希望尽可能提高效率,这样如果我想从星期五开始预订,我宁愿找到一个在星期四之前保留的项目(因此,从周五免费).

对于双重奖励标记,如果我需要X天的物品,我想在预订中找到一个洞,尽可能接近X天.

我认为问题是我试图找到一些不存在的东西(现有的预订).我找到的所有其他解决方案似乎都有一个可预订日期表,其中包含项ID(值为NULL,0或-1表示"尚未预订").这对我来说似乎效率低下.这张桌子会延伸到未来多远?

注意:有些人在询问读写比例.显然每个预订只进行一次,所以这是一次写入(可能每天一次,具体取决于实现),并且当用户搜索未预订的插槽时,我希望有多次读取.

Gus*_*tek 6

SELECT item FROM reservations WHERE 
(endDate BETWEEN start AND end) OR (startDate BETWEEN start AND end) OR (startDate<start AND endDate>end)
Run Code Online (Sandbox Code Playgroud)

通过@Strawberry建议,更好的查询将如下所示

SELECT item FROM reservations WHERE
start<endDate AND end>startDate
Run Code Online (Sandbox Code Playgroud)

这将为您提供您正在寻找的日期所拍摄的物品.现在您需要查找不在此列表中的项目.所以如果你有一个带有项目的表你可以像这样写smth

SELECT * FROM items WHERE item NOT IN 
SELECT item FROM reservations WHERE
start<endDate AND end>startDate)
Run Code Online (Sandbox Code Playgroud)

并且您可以获得在搜索期间免费的项目.

开始,结束是日期您查找startDate,endDate是列.

SELECT item, start-r.startDate as diff FROM items as i 
LEFT JOIN reservations as r USING(item) 
WHERE i.item NOT IN 
(SELECT item FROM reservations WHERE
start<endDate AND end>startDate
) ORDER BY diff
Run Code Online (Sandbox Code Playgroud)

没有架构来测试它,但这个查询应该是你的第一个奖金的答案

至于第二,这需要在一个表的行之间进行一些数学运算,现在我不介意如何在纯MySQL中如果可能的话.

//编辑

在现有预订开始之前和搜索期间之后结束时,我更新了一个条件.

对于第二个奖金问题,这应该工作

SELECT item, r1.startDate-r2.endDate as diff FROM reservations as r1 JOIN (SELECT * FROM reservations) as r2 USING (item)
WHERE r1.startDate-r2endDate>=x AND item NOT IN
(SELECT item FROM reservations WHERE
r1.startDate<endDate AND r2.endDate>startDate)
ORDER BY diff ASC
Run Code Online (Sandbox Code Playgroud)

但这将是非常昂贵的查询.可能需要在子查询中的日期中添加/减去一天.

正如你在所有这些中看到的那样,我在帖子的开头使用查询作为子查询,对于第一和第二个查询,这不会是一个大问题,因为它只执行一次.在第二次奖励的最后查询中,必须分别对每一行执行(因为每个项目都有一个连接,给定项目的预留次数为2)并且它可能是瓶颈.

我不知道你要预订的那些项目是什么,但是如果它们不是很多<1000它可能足够快(每年最多可达365000行)但是如果项目数量真的很大可能你可以使额外的条件在未来一年看起来最大,并且只在必要时增加它,加上分区它可以很快地工作.