1

作業中のWebサイトに検索機能を実装する方法に問題があります。

検索フォームには、ユーザーがレンタカーを借りたい開始日と終了日の2つのフィールドがあります。

データベースには2つのテーブルがあります。1つは車両用で、もう1つは利用可能な日付用です。

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の各行は、関連する車がレンタルまたは予約できる日を表します。

問題:

ユーザーが2013年2月5日から2013年2月8日まで利用可能な車を検索した場合、ユーザー選択ですべての日に利用可能なすべての車を選択するためのクエリを実行したいと思います。

私の現在の未完成の解決策:

私はこのようなものを使って一日中繰り返すことができることを知っています

$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];
      }
    }

}

この後、私はすべての日を利用できるかもしれない車の配列を持っているでしょう、しかし私はそれを見つけるためにいくつかの追加の計算をする必要があるでしょう。

より良いクエリを使用して、この問題に対してより洗練された解決策があるかどうかを知りたいです。

これについてフィードバックをいただければ幸いです。

ありがとう

4

1 に答える 1

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 の例があります)
このクエリは、1 日に 1 つのエントリしかないことを前提としています。基本的に、開始日よりも大きい/等しい、および「終了」日よりも前のすべての「使用可能な」行を取得します (日付/時刻/タイムスタンプは... 複雑です。この記事では SQL Server 固有の問題を扱いますが、基本的な概念が適用されます)、それらの間の日数を数えるための 1 つがあることを確認します。HAVINGほとんどの場合、句を探していました。
の適切なインデックスが与えられたCars_Availability場合、テーブルにヒットすることさえない可能性があり、これも優れたパフォーマーになります。

于 2013-02-01T00:55:36.617 に答える