1

我已经为此工作了几天,但我无法弄清楚。我希望你能帮助我。

我正在开发预订系统,我想检查 DATE 和 TIME 是否有可用的桌子。这就是我的数据库的样子。

在此处输入图像描述

我想将可用表放入选择下拉菜单中,因此在网站上它只显示可用表。

如果我使用以下查询,我可以获得储备表

SELECT res.reserveringsnr, datum, begintijd, eindtijd, tafr.tafelnr FROM reserveringen AS res
INNER JOIN tafels_regel AS tafr
ON res.reserveringsnr = tafr.reserveringsnr
WHERE (res.datum = "2013/12/18" AND (res.begintijd BETWEEN "12:00:00" and "14:00:00"))

因此,该查询将保留表排除在外,但这就是我卡住的地方。我不知道如何检查某个表是否在 DATE 和 TIME 上保留。

(注意:日期和时间将由变量填写,但对于示例我只使用文本)

编辑:处理@sebt 他的解决方案

首先,回答你的问题

  1. 预订总是在同一天
  2. 预订有固定的时间,总是 2 小时。

我已经编辑了 sebt 对我的价值观的查询:

    SELECT t.* FROM
    tafels t
LEFT JOIN
    (SELECT tafelnr FROM
          tafels_regel tf
    INNER JOIN
          reserveringen res
    ON tf.reserveringsnr=res.reserveringsnr
    WHERE
    res.datum="2012/01/12" AND
    res.begintijd<"19:00:00" AND
    res.eindtijd>"21:00:00" 
    )
ReservationsAtThisTime
ON t.tafelnr=ReservationsAtThisTime.tafelnr
WHERE ReservationsAtThisTime.tafelnr IS NULL

此查询输出以下结果 在此处输入图像描述

如您所见,查询结果显示所有 tafels (12)。

我还将表 reserveringen、tafels_regel 和 tafels 导出到 .csv(请参阅下面的已编辑 .csv)

编辑2:

好吧,我再次编辑了我的查询,它适用于一部分。这是查询(截图

    SELECT t.* FROM
    tafels t
LEFT JOIN
    (SELECT tafelnr FROM
          tafels_regel tf
    INNER JOIN
          reserveringen res
    ON tf.reserveringsnr=res.reserveringsnr
    WHERE
    res.datum="2013/01/12" AND
    res.begintijd <= "19:00:00" AND
    res.eindtijd >= "21:00:00" 
    )
ReservationsAtThisTime
ON t.tafelnr=ReservationsAtThisTime.tafelnr
WHERE ReservationsAtThisTime.tafelnr IS NULL

2013/01/12 有 2 个预订。(下载编辑的.csv)

预约1:tafel 1 19:00-21:00

预订2:tafel 11 和 tafel 12 20:00 至 22:00

当我运行上面的查询时,唯一没有显示的 tafel 是 tafel 1,因为 tafel 1 是从 19:00 到 21:00 保留的。但是,从 20:00 到 22:00 tafel 11 和 12 也保留。

在查询结果中可以看到,只有 tafel 1 是 reserverd。但是,当我从 19:00 到 21:00 进行另一次预订时,我正在检查可用的 tafel,然后 tafel 11 和 tafel 12 仍然显示。

tafel 19:00 是免费的,没错,但因为我们总是坐 2 个小时,所以我们不能坐在那里。

再次感谢@sebt 的输入,希望您能通过此查询进一步帮助我!

问题解决了

感谢大家的帮助,这是最后的查询

SELECT t.* FROM
    tafels t
LEFT JOIN
    (SELECT tafelnr FROM
          tafels_regel tf
    INNER JOIN
          reserveringen res
    ON tf.reserveringsnr=res.reserveringsnr
    WHERE
    res.datum="2013/01/12" AND
    res.eindtijd > "19:00:00" AND
    res.begintijd < "21:00:00" 
    )
ReservationsAtThisTime
ON t.tafelnr=ReservationsAtThisTime.tafelnr
WHERE ReservationsAtThisTime.tafelnr IS NULL
4

2 回答 2

1

我认为您的问题措辞有点令人困惑,因为 SQL“表”(数据库表)与数据库中的一个对象(我猜)是餐厅表之间的歧义,在荷兰语中称为“tafel” ?

(让我们继续称它们为“tafel”,因为这样可以消除歧义)

要仅选择未保留的 tafels 您可以将所有 tafels 加入到 [desired time] 当前的保留集,并仅返回没有此类保留的 tafels:

SELECT t.* FROM
    Tafels t
LEFT JOIN
    (SELECT tafelnr FROM
          Tafels_regel tf
    INNER JOIN
          Reserveringen res
    ON tf.reserveringnr=res.reserveringnr
    WHERE
    res.Datum=[desired date] AND
    res.begintijd<[desired time] AND
    res.eindtijd>[desired time]
    ) ReservationsAtThisTime
ON t.tafelnr=ReservationsAtThisTIme.tafelnr
WHERE ReservationsAtThisTime.tafelNR IS NULL

这可能仍需要一些调整,例如:

  1. 跨天的预订(即盯着某一天并在另一天结束)将无法正确处理。(但也许你不需要这个)
  2. 一张桌子将在 10/01/2012 12:30 显示为可用,而实际上它是从 2012 年 1 月 1 日 12:45 开始保留的(也许没有人对至少在 10/01/2012 不免费的桌子感兴趣X 分钟 - 1 小时? - 在他们想要的开始时间之后?)。

编辑(在下面回答 OP 的评论):

查看您的数据,我可以看到您在 2013 年 1 月 12 日的 19:00 到 21:00 预订了 Tafel 1。我明白为什么您没有得到预期的结果(即不应显示 Tafel 1,因为它不是免费的):

  1. 您在查询中使用的日期是 2012 年而不是 2013 年。(这可能源于我的示例,我使用 2012 年)
  2. 我将示例设计为使用单个时间点“期望时间”。我的想法是,“所需时间”将是一个点(例如 19:30) - 因此从(例如)19:00 开始到 20:00 结束的预订将使这个所需时间不可用。因为您使用的“期望时间”是一个范围(19:00 到 21:00),并且恰好与预订的范围完全一样,所以查询中的“<”和“>”是由于与“期望时间”冲突(“<=”和“>=”会解决此问题),因此未能获取此保留。

但是,由于您说所有预订都是 2 小时,因此仅使用所需的开始时间来指定“冲突预订”会更容易,如下所示:“冲突预订”是指在 2 小时内占用任何时间的预订所需的开始时间:

一个。res.Datum = [期望日期];和 b。res.eindtijd>[期望的开始时间];和 c。res.begintijd<[期望的开始时间 + 2 小时]

我不完全确定代码将如何工作以增加 2 小时(我的专长是 MS-SQL 而不是 MySQL,日期/时间操作可能有点特定于 SQL 的版本)。

EDIT2(回答 OP 重新编辑的问题):

为了让事情更清楚,我将定义这些术语:

现有预订:数据库中已存在。有 TafelNr、Date、StartTime (begintijd) 和 EndTime (eindtijd)

建议的的预订:用户想要进行的预订 - 自然它在数据库中尚不存在,或者有 TafelNr。有日期、开始时间、结束时间。

(您已经使用 StartTime 和 EndTime 为 Proposed booking 实现了查询。我建议只使用 StartTime,然后使用 [StartTime+2 hours]。但是您使用的哪种方式对我们正在谈论的问题)

你是对的,如果查询工作正常,不应该显示 tafels 11 和 12。您在 19:00 至 21:00 期间提出的预订应与 20:00 至 22:00 的现有预订发生冲突。但正如您所发现的,这种冲突并没有按应有的方式检测到。

原因是您的开始/结束时间比较略有错误。你编码的方式:

res.begintijd <= [Proposed Start time] AND
res.eindtijd >= [Proposed End time]

只会发现现有预订有冲突,如果它跨越提议的预订,则只会发现它存在冲突:完全相同的时间,或在提议的预订之前和/或之后延长。

将两个预订(现有的和提议的)想象成平行的乐高积木沿相邻线滑动是有帮助的。他们根本无法联系(好);或者只是联系(一个人的结束=另一个人的开始:好,没有冲突 - 只是!);或者一个的结束可以延伸到另一个的开始(冲突);或者一个可以跨越另一个,同时开始或在另一个之前开始,并与另一个同时或稍后结束(冲突)。

这是我多年前在使用预订系统时发现的一个技巧。找到冲突的正确比较(如我上面之前的编辑)是:

ExistingBookingEndTime>ProposedBookingStartTime AND
ExistingBOokingStartTime<ProposedBookingEndTime

或者,使用您的对象名称:

res.eindtijd>"19:00:00" AND
res.begintijd<"21:00:00"

起初这可能没有意义,但如果您考虑乐高积木,它就会有意义。

请注意

1.我使用 < 和 >,而不是 <= 和 >=,因为我假设预订可以相互延伸并“接触”,只要它们不重叠;

2.比较日期和时间时要小心——如果只是比较它们,就好像它们是数字或字符串一样,它可能会给出奇怪的结果。我不知道 MySQL 是如何处理这个问题的,但这是我一直很小心/偏执的事情。

于 2013-01-09T14:09:17.347 回答
0

好吧,我不太了解您的数据库结构。但是为了让你走上正轨:

  1. 您可以简单地查询所有表
  2. 从结果集中排除反转表

就像是:

SELECT tafelnaam FROM Tafels WHERE tafelnr NOT IN (SELECT tafelnr *OF YOUR RESEVED TABLES*)
于 2013-01-09T13:38:23.797 回答