查询车辆的可用租赁日期

时间:2013-01-31 22:51:33

标签: php mysql sql

我在如何在我正在处理的网站上实现搜索功能时遇到了麻烦。

搜索表单有两个字段,即用户想要租用车辆的起始日期和结束日期。

在数据库中,我有两个表,一个用于车辆,另一个表用于可用日期。

Table: cars
 - car_id (int)
 - name (varchar)
 - description (varchar)

Table: cars_availability
 - car_id (int)
 - date (datetime)
 - status (int) // 1: available 2: booked

cars_availability 中的每一行代表关联汽车可供出租或预订的日期。

问题:

如果用户搜索可从 5.feb.2013 8.feb.2013 的汽车,我想查询选择所有的汽车可供用户选择的所有日期使用。

我目前尚未完成的解决方案:

我知道我可以使用类似的东西遍历所有日子

$begin = new \DateTime( date('Y-m-d', strtotime($data['rent_start'])));
$end = new \DateTime( date('Y-m-d', strtotime($data['rent_end'])));
$end = $end->modify( '+1 day' ); 

$interval = \DateInterval::createFromDateString('1 day');
$period = new \DatePeriod($begin, $interval, $end);

$available_cars = array();

foreach ( $period as $dayTime ){

    // query the cars and joining the cars_availabilty table

    $item = DB::select('cars.*')
    ->from('cars')
    ->join('cars_availability')->on('cars_availability.item_id', '=', 'cars.item_id')
    ->where('items_availability.date', '=', $dayTime->format("Y-m-d H:i:s"))
    ->and_where('items_availability.status', '=', 1)
    ->execute()->as_array();

    if(count($item) > 0){

      if(isset($available_cars[$item[0]['item_id']])){

        $available_cars[$item[0]['item_id']][] = $item[0];

      }else{

        $available_cars[$item[0]['item_id']] = array();
        $available_cars[$item[0]['item_id']][] = $item[0];
      }
    }

}

在此之后,我会有一系列可能有所有日子可用的车辆,但我需要做一些额外的数学计算才能找到它。

我想知道是否有更优雅的解决方案来解决这个问题,可能会使用更好的查询。

如果你能给我任何反馈,我将非常感激。

由于

1 个答案:

答案 0 :(得分:2)

这实际上是一个相当理智的查询设置。就个人而言,我建议遵循@inhan的建议,特别是如果事实证明汽车可以预订更短的时间(几小时?)。但是,由于边缘情况,查询会变得有点复杂(如果你在这里看一下,你应该找到相关的例子)。

不幸的是,我无法谈论它如何适合您的框架,但SQL可能如下所示:

SELECT Cars.car_id, Cars.name, Cars.description
FROM Cars
JOIN (SELECT car_id
      FROM Cars_Availability
      WHERE `date` >= '2013-02-05'
            AND `date` < '2013-02-09'
            AND status = 1
      GROUP BY car_id
      HAVING COUNT(*) = DATEDIFF('2013-02-09', '2013-02-05')) Available
  ON Available.car_id = Cars.car_id

(有一个SQL Fiddle Example
此查询假设每天只有一个条目,或者这个条目中断。基本上,它抓取每个“可用”行大于/等于开始日期,小于“结束”日期(日期/时间/时间戳是......复杂; this article处理SQL Server特定的问题,但基本概念适用),并确保它们之间的天数。大多数情况下,您正在寻找HAVING条款 鉴于Cars_Availability上的正确索引,它甚至可能不会出现在桌面上,这也是一个很好的表现。