简体   繁体   English

PHP / SQL-如何检查日期用户输入是否在数据库中现有日期范围之间?

[英]PHP/SQL - How can I check if a date user input is in between an existing date range in my database?

I am trying to create a search page that takes a check in and check out date to check if a room is available. 我正在尝试创建一个需要签入和签出日期以确认是否有空房的搜索页面。 if a room has an existing booking and its date range overlaps with the user input then it is not outputted. 如果房间已有预订,并且日期范围与用户输入重叠,则不会输出。 otherwise if it does not have a booking or its current bookings does not overlap with user input then it is outputted. 否则,如果没有预订或当前预订与用户输入不重叠,则将其输出。 A check in can exist on another booking's check out date 可以在另一个预订的退房日期进行入住

My current SQL outputs all rooms based on the number of beds only. 我当前的SQL仅根据床位数输出所有房间。 for some reason it does not check for date overlaps. 由于某种原因,它不检查日期重叠。

$sql13 = "SELECT rid, beds, orientation, price FROM rooms 
          WHERE beds = $nOfBeds AND rooms.rid NOT IN 
         (SELECT bookings.rid FROM bookings 
          WHERE $cInDate BETWEEN checkin AND checkout OR 
         ($cInDate <= checkin AND $cOutDate >= checkout))";

if ($rOrientation != "") {
    $sql13 .= " AND orientation = '$rOrientation'";
}
$results13 = mysqli_query($conn, $sql13)
or die ('Problem with query' . mysqli_error($conn));

there are more rooms. 还有更多的房间。 I just took a smaller screenshot to make the question smaller 我只是截了一个较小的屏幕截图以使问题变小

It's pretty simple to check for an overlap of time periods. 检查时间段是否重叠非常简单。

Let b1 and e1 represent start and end of period 1, with b1 before e1 b1e1代表周期1的开始和结束, b1e1之前

Let b2 and e2 represent start and end of period 2, with b2 before e2 b2e2代表周期2的开始和结束, b2e2之前

If there is no overlap in the periods, then we know that the following will return TRUE 如果期间没有重叠,那么我们知道以下内容将返回TRUE

 ( b1 > e2 OR b2 > e1 )

(basically, the beginning of one period will be after the end of the other period.) (基本上,一个时期的开始将在另一时期的结束之后 。)

Given that the periods in the question are defined by just dates (with no time components), assuming that "checkout time" of one booking period will be sufficiently before "checkin time" of a subsequent booking period, giving enough time between for the overworked and underpaid housekeeping staff to clean the room... then we wouldn't consider a checkin date equal to a checkout date of another period to be an overlap... so equals wouldn't be a considered an overlap 假设问题中的时间段仅由日期(没有时间部分)定义,则假设一个预订时间段的“结帐时间”将在随后的预订时间段的“结帐时间”之前足够,从而为过度劳累提供了足够的时间和低薪的客房服务人员打扫房间...那么我们将不认为入住日期等于另一个期间的退房日期是重复的...因此等于不被视为重复

 ( b1 >= e2 OR b2 >= e1 )

Conversely, if there is an overlap in the periods, then the negation of that condition would return TRUE 相反,如果时间段的重叠,则该条件的否定会返回TRUE

 NOT ( b1 >= e2 OR b2 >= e1 )

To find "rooms" available for a specified period (ie no overlapping bookings), we could use an anti-join pattern: 为了找到在指定时期内可用的“房间”(即没有重复的预订),我们可以使用反加入模式:

  SELECT r.rid
       , r.beds
       , r.orientation
       , r.price
    FROM rooms r
    LEFT
    JOIN bookings b
      ON b.rid = r.rid
     AND NOT ( ? >= b.checkout OR ? <= b.checkin )
   WHERE b.rid IS NULL
     AND r.beds = ?

The question marks are placeholders for checkin, checkout and number of beds, in that order. 问号是按此顺序签入,签出和床位数的占位符。 (We prefer to use prepared statements with bind placeholders, for a couple of reasons... to avoid creating unnecessary SQL Injection vulnerabilities, and in some databases, potential for improved performance.) But feel free to substitute those question mark placeholders in the SQL text with appropriately validated and properly escaped literal expressions. (出于两个原因,我们倾向于将准备好的语句与绑定占位符一起使用...以避免避免产生不必要的SQL Injection漏洞,并且在某些数据库中可能会提高性能。)但是请随时在SQL中替换那些问号占位符具有正确验证和正确转义的文字表达式的文本。

The way to understand the anti-join... the outer join returns all rows from rooms, along with any matching overlapping bookings. 了解反联接的方式...外部联接返回房间中的所有行,以及所有匹配的重叠预订。 If there are no "matching" (overlapping) rows from bookings, the row from rooms will be returned, with all NULL values for the columns from bookings. 如果预订中没有“匹配”(重叠)行,则将返回房间中的行,其中包含预订列中的所有NULL值。 So we can exclude all rooms that had at least one matching (overlapping) row from booking with a simple test in the WHERE clause. 因此,我们可以通过WHERE子句中的简单测试将所有至少具有一个匹配(重叠)行的房间排除在预订之外。 If there was a matching row, we know that the rid column from booking would have a non-NULL value. 如果有匹配的行,我们知道预订的rid列将具有非NULL值。 If we exclude all rows with non-NULL values, we are left with rooms that didn't have an overlapping booking. 如果我们排除所有具有非NULL值的行,则会留下没有重复预订的房间。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM