【问题标题】:Select between two date在两个日期之间选择
【发布时间】:2018-02-12 21:16:18
【问题描述】:

嗨!

我有两张桌子,“房间”和“忙碌”。我的忙碌表包含包含到达日期和离开日期的预订记录。

我希望选择两个给定日期都没有预订的房间。

有人给了我他想要预订房间以及他打算离开的日期,我希望能够显示他可以使用的房间。

忙桌 => |IdRoom||ArrivalDate|DepartureDate|

Room Table => |IdRoom|NumRoom|等等..|

我尝试了不同的查询,但没有得到任何结果。

我测试过的查询:

SELECT Room.*, Busy.* 
FROM Room
INNER JOIN Busy ON Room.RoomdId= Busy.RoomdId
WHERE (@dateArr NOT BETWEEN 'Busy.ArrivalDate' AND 'Busy.DepartureDate') 
AND (@dateDep NOT BETWEEN 'Busy.ArrivalDate' AND 'Busy.DepartureDate')

提前感谢您的帮助!

【问题讨论】:

  • 您已经用字符串标识符封装了列。此外,BETWEEN 具有包容性,这可能会影响您的预期结果(一旦您解决了列问题)。
  • 您使用的是哪个 DBMS? mysql sql server access 在任何情况下,您都需要摆脱 where 谓词中的字符串文字。您想与表列进行比较,而不是字符串。并小心使用...sqlblog.org/2011/10/19/…
  • 最好的答案将涉及数字表...根据您的 dbms,使用或生成数字表看起来非常不同。
  • 哦,首先,删除 Busy.ArrivalDateBusy.DepartureDate 周围的单引号。
  • @JacobH 我执行了不带引号的查询,结果是一样的:没有结果。

标签: sql database ms-access


【解决方案1】:

好的,我已经更正了我的查询。

这是我使用的查询:

SELECT * 
FROM Room 
WHERE RoomId in (
             SELECT RoomID FROM Reservation WHERE EndDate <= @startDate OR  
             StartDate >= @endDate
             )

肯定有更好的方法来做到这一点,但它确实有效。 谢谢大家帮助我;)

【讨论】:

  • 我已经加了这个,它比我的要简单得多。但会错过任何从未预订过的房间。
【解决方案2】:

您尝试使用的查询在逻辑上是错误的。内连接在这里没有用。请检查下面的查询

SELECT Room.*
FROM Room
WHERE NOT EXISTS 
(
   SELECT 1 FROM Busy WHERE Room.RoomdId= Busy.RoomdId AND
     (@dateArr BETWEEN 'Busy.ArrivalDate' AND 'Busy.DepartureDate') AND 
     (@dateDep BETWEEN 'Busy.ArrivalDate' AND 'Busy.DepartureDate')
)

【讨论】:

  • 完美地完成了这项工作!我会审查我的加入,谢谢;)
  • 如果解决方案有效,请您投票并将其标记为解决方案吗?谢谢
  • 这怎么能行呢?语法错误(单引号)并且逻辑错误。例如,当您的日期为 2018-01-01 和 2018-02-01,并且房间在 2018-01-15 - 2018-01-17 被占用时,它不会检测到重叠。
【解决方案3】:

多看几列表格会很有帮助。您可能需要考虑重构它们 - 它们似乎不是第 3 范式。此外,还不清楚 BUSY 表是否包含所有房间出租时间的完整历史记录。如果 BUSY 仅包含当前预订,这应该可以工作:

选择 IdRoom 从忙 WHERE @ArrivalDate >= DepartureDate AND @DepartureDate

【讨论】:

    【解决方案4】:

    首先,您的引号有问题。但我认为这可能只是将价值观置于问题中。

    其次,您不想要来自busy 的列。没有匹配,所以它们不感兴趣。

    那么重叠逻辑不正确。比如:

    SELECT r.*
    FROM Room r LEFT JOIN
         Busy b
         ON r.RoomdId = b.RoomId AND
            @dateArr <= b.DepartureDate AND
            @dateDep >= b.ArrivalDate
    WHERE b.RoomId IS NULL;
    

    您的问题不清楚是否有人可以在出发日期到达(反之亦然)。如果是这样,&lt;=&gt;= 可能需要丢失相等比较。

    编辑:

    在 MS Access 中,您可以使用NOT EXISTS

    SELECT r.*
    FROM Room r LEFT JOIN
    WHERE NOT EXISTS (SELECT 1
                      FROM Busy b
                      WHERE r.RoomdId = b.RoomId AND
                            @dateArr <= b.DepartureDate AND
                            @dateDep >= b.ArrivalDate
                     );
    

    【讨论】:

    • 我收到错误消息:“不支持 JOIN 表达式。”
    • Praytell,您使用的是什么数据库?这是完全有效的语法。
    • 我使用 Access 数据库。我对此毫无疑问,但不幸的是它不起作用。
    【解决方案5】:

    在 4 种情况下,日期比较应该显示房间很忙。 @Simonare 通过对繁忙的房间使用子选择,然后将它们从主要的SELECT * FROM Room 中排除在正确的轨道上@

    我笨拙的小表格说明了 4 种失败场景:

    12345678 -> Eight Dates in a row.
    ..BBBB.. -> Assume: These four Dates are 'B' busy. 'D' dates below are desired/requested. 
    
    .D...... -> Success: Desired is before busy dates
    ......D. -> Success: Desired is after busy dates
    ..DD.... -> Fails: Desired within busy dates
    .DD..... -> Fails: Desired overlaps starting before beginning of busy dates
    .....DD. -> Fails: Desired overlaps extending after ending of busy dates
    .DDDDDD. -> Fails: Desired extends both before and after busy dates
    

    这些是用于消除故障的WHERE 子句:

    在繁忙日期内请求:繁忙到达日期 AT 或 AFTER 希望到达日期 AND 繁忙出发日期 LE 希望出发日期

    SELECT 'Busy.DateArr' <= @dateArr AND  'Busy.DateDep' >= @dateDep
    

    请求在忙碌开始之前开始:所需的到达日期在忙碌的到达日期之前,而所需的出发日期在忙碌的到达日期之后)

    SELECT @dateArr < 'Busy.DateArr' AND @dateDep > 'Busy.DateArr'
    

    请求在忙碌结束后结束:所需到达日期在忙碌出发日期之前,所需出发日期在忙碌出发日期之后

    SELECT @dateArr < 'Busy.DateDep' AND @dateDep > 'Busy.DateDep'
    

    请求超出开始和结束时间:所需的到达日期是在繁忙的到达日期之前,而希望的出发日期是在繁忙的出发日期之后

    SELECT @dateArr < 'Busy.DateArr' AND  @dateDep > 'Busy.DateDep'
    

    所以整个 SQL 就变成了……

    SELECT * FROM Room
      WHERE NOT EXISTS ( 
       SELECT 1 FROM Busy WHERE Room.RoomdId= Busy.RoomdId AND
       ((@dateArr>= 'Busy.DateArr' AND @dateDep<= 'Busy.DateDep') OR
        (@dateArr < 'Busy.DateArr' AND @dateDep > 'Busy.DateArr') OR
        (@dateArr < 'Busy.DateDep' AND @dateDep > 'Busy.DateDep') OR
        (@dateArr < 'Busy.DateArr' AND @dateDep > 'Busy.DateDep') )
     )
    

    抱歉,我实际上并没有运行它,所以由于复杂性,可能存在逻辑或语法错误。您可以单独测试和调试每个 SELECT 部分以确保它们是正确的。此外,明智地使用一点布尔代数可以显着简化语句。

    而且...我假设有人可以在出发日期到达。

    【讨论】:

      猜你喜欢
      • 2017-03-07
      • 2015-07-08
      • 2017-01-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-03
      • 1970-01-01
      相关资源
      最近更新 更多