6

我正在创建一个显示数据库表中的项目的系统,具体取决于它们是否可用。

我有两张桌子:

预订:

----------------------------------------------------------------------
| ResID | CarID | UserID | startTime | startDate | endTime | endDate  |
----------------------------------------------------------------------
|   1   |   4   |    4   | 13:00:00  |2013-04-21 |13:00:00 |2013-04-29|

和汽车:

-------------------------------------------
| CarID  |  make | model | serial | image |
-------------------------------------------
|   1    | Honda | civic | ky675  | 1.png | 

因此,当用户访问一个页面时,他们输入一个开始日期和结束日期,然后在运行查询以检查该汽车是否在该日期可用后显示汽车列表。

所以我想出了这个查询。

$carstring = mysql_query("SELECT * FROM cars 
                            {$statement} 
                            AND deleted = 'no' 
                            AND carID NOT IN (
                              SELECT carID FROM reservations 
                                WHERE startDate = '".$sqlcoldate."'
                            ) 
                          GROUP BY model");

这样做是从数据库中选择所有汽车,然后排除作为子查询的数组结果的汽车 ID 数组。其余的汽车,它按型号分组并在循环中显示它们,如下所示:

$getcars = $carstring;
while($searchcars = mysql_fetch_array($getcars)) {

 **some HTML showing car imag and make etc etc**

 }

这“有效”。例如,如果我有 5 辆 Honda Civic,并且所有这些都在用户输入的日期被保留,他们的 carID 将被排除在循环之外。然而,它根本不会在列表中显示本田思域,因为它们都将消失。

我需要一种方法来判断我是否在某个日期用完了某种型号的汽车。所以我有三个思域,我知道三个被排除在外,所以我展示了一个,但它无法预订。

我认为解决方案是删除子查询。所以首先我运行:

$nonavail = mysql_query("SELECT carID FROM reservations 
                         WHERE startDate = '".$sqlcoldate."'");
while($noavailrow = mysql_fetch_array($nonavail)) { 

这给了我需要排除的一系列汽车 ID,然后我可以抓取所有汽车并使用 PHP 和我的汽车 ID 对它们进行排序。但我现在迷路了……

有人可以指出我正确的方向吗?

4

8 回答 8

7

应该可以这样做:

SELECT    c.make, c.model, count(c.carid) - count(x.resid) available_cars
FROM      cars c
LEFT JOIN (
   SELECT   r.carid, r.resid
   FROM     reservations r 
   WHERE    ? BETWEEN r.startdate AND r.enddate) x ON x.carid = c.carid
WHERE     c.deleted = 'no'
GROUP BY  c.make, c.model
ORDER BY  c.make, c.model

内部子查询将仅选择开始时间在给定时间之前和结束时间之后的那些预订(由 表示?)。外部查询然后选择所有汽车并尝试找到属于每辆车的预订(可以有一个或没有,但永远不会超过一个,因为我猜你不能同时为同一辆车预订多个时间)。最后,结果集按makemodel对每个车辆的总数进行分组,并计算预订数量,差值是可用车辆的数量。

这种方法利用了COUNT()只计算 NULL.

于 2013-03-12T18:35:44.203 回答
1

我将提供一个 PHP 解决方案。SQL 可能是性能更好的选项,所以这实际上只是为了给线程添加一些多样性。

这是我如何理解这个问题。您想要显示可用的汽车以及每个不可用的车型至少有一辆汽车。IE:

  • 福特金牛座 - 可用
  • 福特金牛座 - 可用
  • 本田思域 - 不可用
  • 现代奏鸣曲-Avaialble

...

// Keep track of the models so we know which ones we have already processed
$models = array();

// Filter the array of results
array_filter( $results, function ( $result ) use ( &$models )
{
    // If the model has not yet been represented, add the model to the models 
    // array and return true, preserving this item in the array
    if ( !in_array( $result->model, $models )
    {
        $models[] = $result->model;
        return true;
    }

    // If the car is in the excluded list, remove this item from the array
    if ( in_array( $result->car_id, $excluded_car_ids ) )
    {
        return false;
    }

    return true;
});
于 2013-03-13T03:50:41.763 回答
0

这里给出分离可用和不可预订的汽车列表的解决方案。它对您非常有用。

获取可供预订的车辆列表。IE)。可预订特定日期间隔..

select *,'available' as status from cars where CarID not in(SELECT CarID FROM reservations
WHERE UNIX_TIMESTAMP( CONCAT( startDate,  ' ', startTime ) ) <= $startTimestamp
AND UNIX_TIMESTAMP( CONCAT( endDate,  ' ', endTime ) ) >= $endTimestamp)WHERE deleted = 'no' group by make,model order by make,model asc

获取不可预订的汽车列表。IE)。已为特定日期间隔保留..

select *,'not available' as status from cars where CarID not in(SELECT CarID FROM reservations
WHERE UNIX_TIMESTAMP( CONCAT( startDate,  ' ', startTime ) ) <= $startTimestamp
AND UNIX_TIMESTAMP( CONCAT( endDate,  ' ', endTime ) ) >= $endTimestamp)WHERE deleted = 'no' group by make,model order by make,model asc

注意:将日期转换为时间戳格式..

$startDateTime="21/04/2013 13:00:00"; //date example
list($sDay, $sMonth, $sYear, $sHour, $sMinute,$sSeconds) = split('[/ :]', $startDateTime); 
$startTimestamp=mktime($sHour, $sMinute,$sSeconds, $sMonth, $sDay, $sYear);

$endDateTime="29/04/2013 13:00:00"; //date example
list($eDay, $eMonth, $eYear, $eHour, $eMinute,$eSeconds) = split('[/ :]', $endDateTime); 
$endTimestamp=mktime($eHour, $eMinute,$eSeconds, $eMonth, $eDay, $eYear);

代码如下:

<?php
$startDateTime="21/04/2013 13:00:00"; //date example
list($sDay, $sMonth, $sYear, $sHour, $sMinute,$sSeconds) = split('[/ :]', $startDateTime); 
$startTimestamp=mktime($sHour, $sMinute,$sSeconds, $sMonth, $sDay, $sYear);

$endDateTime="29/04/2013 13:00:00"; //date example
list($eDay, $eMonth, $eYear, $eHour, $eMinute,$eSeconds) = split('[/ :]', $endDateTime); 
$endTimestamp=mktime($eHour, $eMinute,$eSeconds, $eMonth, $eDay, $eYear);

$carstringAvailable = mysql_query("select *,'available' as status from cars 
                            WHERE CarID not in(
                                SELECT CarID FROM reservations
                                WHERE UNIX_TIMESTAMP( CONCAT( startDate,  ' ', startTime ) ) <= $start_Timestamp
                                  AND UNIX_TIMESTAMP( CONCAT( endDate,  ' ', endTime ) ) >= $end_Timestamp
                                  )
                            AND deleted = 'no' group by make,model order by make,model asc");

$getcarsAvailable = $carstringAvailable;
?>
<h3>Available cars for reservation</h3>
<table>
<tr>
    <th>CarID</th><th>make</th><th>model</th><th>serial</th><th>image</th><th>status</th>
</tr>
<?php 
if(mysql_num_rows($getcarsAvailable)>0)
{
    while($searchcarsAvail = mysql_fetch_array($getcarsAvailable)) 
    {
    ?>
    <tr>
        <td><?php echo $searchcarsAvail['CarID'];?></td>
        <td><?php echo $searchcarsAvail['make'];?></td>
        <td><?php echo $searchcarsAvail['model'];?></td>
        <td><?php echo $searchcarsAvail['serial'];?></td>
        <td><?php echo $searchcarsAvail['image'];?></td>
        <td><?php echo $searchcarsAvail['status'];?></td>
    </tr>
    <?php
    } 
}
else 
{
?>
    <tr>
        <td colspan='5'>No records found</td>
    </tr>
<?php 
}
?>
</table>

<?php 
$carstringUnAvailable = mysql_query("select *,'available' as status from cars 
                            WHERE CarID in(
                                SELECT CarID FROM reservations
                                WHERE UNIX_TIMESTAMP( CONCAT( startDate,  ' ', startTime ) ) <= $start_Timestamp
                                  AND UNIX_TIMESTAMP( CONCAT( endDate,  ' ', endTime ) ) >= $end_Timestamp
                                  )
                            AND deleted = 'no' group by make,model order by make,model asc");

$getcarsUnAvailable = $carstringUnAvailable;
?>
<h3>Already Reserved cars list</h3>
<table>
<tr>
    <th>CarID</th><th>make</th><th>model</th><th>serial</th><th>image</th><th>status</th>
</tr>
<?php
if(mysql_num_rows($getcarsUnAvailable)>0)
{ 
    while($searchcarsUnAvail = mysql_fetch_array($getcarsUnAvailable)) 
    {
    ?>
    <tr>
        <td><?php echo $searchcarsUnAvail['CarID'];?></td>
        <td><?php echo $searchcarsUnAvail['make'];?></td>
        <td><?php echo $searchcarsUnAvail['model'];?></td>
        <td><?php echo $searchcarsUnAvail['serial'];?></td>
        <td><?php echo $searchcarsUnAvail['image'];?></td>
        <td><?php echo $searchcarsUnAvail['status'];?></td>
    </tr>
    <?php 
    }
 }
 else 
{
?>
    <tr>
        <td colspan='5'>No records found</td>
    </tr>
<?php 
}
?>
</table>
于 2013-03-19T13:08:13.927 回答
0
$carstring = mysql_query("SELECT *,(SELECT count(CarID) FROM reservations WHERE reservations.CarID=cars.CarID AND '".$sqlcoldate."' NOT BETWEEN startDate AND endDate ) as availability FROM cars {$statement} AND deleted = 'no' GROUP BY model");

上面的查询将为您提供带有附加字段(可用性)的汽车列表,其中包含可用特定型号的汽车数量,如果汽车不可用,该字段将仅显示零。

于 2013-03-15T11:40:18.607 回答
0

选择品牌和型号的“主列表”,然后加入可用的内容。这可能不是最优化的语法,但很清楚:

select Models.*, Available.* from (select make, model from Cars 
GROUP BY make, model) as Models
LEFT JOIN (SELECT * FROM Cars WHERE CarID NOT IN (1,3,6)) as Available on Models.model = Available.model

您会注意到,出于测试目的,我删除了排除保留汽车的逻辑并将其替换为 NOT IN。但它很容易让您重新插入。

http://sqlfiddle.com/#!2/266db/12/0

于 2013-03-13T17:54:59.527 回答
0

我有一个类似的问题要解决。

首先,您必须了解您要在包含您预订的汽车的数据库中寻找未预订的汽车......

您正在寻找不在您的数据库中的信息!
但是你可以从你所拥有的东西中扣除它。

为了简化比较挑战,您应该将您的日期和时间(在您的预订表和两个用户标准 - 开始和结束 - 中)加入“时间戳”格式......将所有现有预订与用户请求。有关格式信息,
请参见:http ://db.apache.org/derby/docs/10.7/ref/rrefsqlj27620.html。

因此,您必须使用您的用户数据(开始和结束时间戳)查找您预订的汽车,并将它们从所有可能的汽车中过滤掉。

                  用户开始 用户结束
                         | |
案例A |--------| | |
案例B |--|--------| |
案例C | |-----------| |
案例 D | |-------|---|
案例E | | |-----------|
案例 F |--------|-----------------|----------------|
                         | |


您需要案例 A 和 E。

此脚本应找出案例 B、C、D 和 F... 并将所有 CarID 放入我称为“NotAvaibleCars”的数组中。
它忘记了案例 A 和 E(过去/完成的预订和未来的预订)。

然后,您必须检查每辆车的 ID 是否为“inArray”,然后才能在结果页面上显示。

代码:

$allReservedCars = mysql_query("SELECT * from reservation") or die(mysql_error());

$allCars = mysql_query("SELECT * from cars") or die(mysql_error());

$NotAvailableCars = array();

$userStart = $_POST['yourClientStartCriteria'];
$userEnd = $_POST['yourClientEndCriteria'];

while ($allCarsCheck = mysql_fetch_array($allReservedCars)){
$TimestampStart = $allCarsCheck['startDate'] . ' ' . $allCarsCheck['startTime'];
$TimestampEnd = $allCarsCheck['startDate'] . ' ' .$allCarsCheck['startTime'];

if (
    (($TimestampStart>$userStart)&&($TimestampStart<$userEnd)) ||   // if cases C or D (A reservation start already exist for this car between userStart and userEnd)
    (($TimestampEnd>$userStart)&&($TimestampEnd<$userEnd)) ||       // if case B or C (A reservation end already exist for this car between userStart and userEnd)
    (($TimestampStart<$userStart)&&($TimestampEnd>$userEnd))        // if case F (A reservation that wraps userStart and userEnd already exist for this car)
   ) {

   array_push($NotAvailableCars, $allCarsCheck['CarID']); // You have now an array of the NOT available cars.

   }

}


while($searchcars = mysql_fetch_array($allcars)) {

 if (inArray($searchcars['CarID'],$NotAvailableCars)){
  //Do nothing!
 }
 else{
 // Your code to show this available car.
 }
}


;)


好的... 8 小时后我再次阅读我的解决方案...
我发现我错过了主要问题:在没有可用于品牌/型号组合的汽车时展示一些东西。

我研究了它......并且有一个......一种解决方案。
但我希望有一个更好的......这就是我现在所能看到的。

$distinctMakeModel = mysql_query("SELECT distinct make, model from cars");
while ($row = mysql_fetch_array($distinctMakeModel)){
  array_push($CarModelArray, $row['make'] . ' -splitter- ' . $row['model']) // Array with all make/model combination

}

$CarQtyArray = array();
for($i=0;$i<$CarModelArray.length;$i++){
  $thisCar = explode(' -splitter- ',$carModelArray[$i]);

  $ThisCarQty = mysql_query("SELECT count(*) from cars where make=$thisCar[0] AND model=$thisCar[1]");
  $thiscar = mysql_fetch_array($ThisCarQty);
  array_push($CarQtyArray, $thiscar[0];     //So now you have an array of quantity with indexes matching the $carModelArray indexes.
}

您现在有一个汽车品牌/型号数组和一个具有匹配索引的数量数组。

下一段代码将创建一个具有相同匹配索引的不可用数量数组。

for($i=0;$i<$CarModelArray.length;$i++){
  $thisCar = explode(' -splitter- ',$carModelArray[$i]);
  $NotAvailableCarQtyArray[$i] = 0;

  for($j=0;$j<$NotAvailableCars.length;$j++){
    $thisNotAvailable = mysql_query("Select count(*) where make=$thisCar[$i] AND model=$thisCar[$i] AND carID=$NotAvailableCars[$j]");
    $isThisTheModel = mysql_fetch_array($thisNotAvailable);
    if ($isThisTheModel<>'0'){
      $NotAvailableCarQtyArray[$i] ++;
    }

  }
}


所以现在...
在 $CarModelArray[0] 中,假设您拥有本田思域。
在 $CarQtyArray[0] 中,您有 3个。
在 $NotAvailableCarQtyArray[0] 中,您有 3 个(全部消失了!)。

for ($i=0;$i<$CarModelArray.length;$i++){
  if ($CarQtyArray[$i]==$NotAvailableCarQtyArray[$i]){
    echo $CarModelArray[$i] . ' are not available.<br>';
  }
}

这需要 waaayyy 在这里进行许多查询!!!
将 SQL 查询放入循环中并不是一个好主意。
但是,再次......我不知道该怎么做。

这就像开始和结束搜索之间的汽车数量乘以您拥有的品牌/型号的数量。

但它应该工作......
至少我试过了。
;)

于 2013-03-14T21:02:43.877 回答
0

据我了解,您想要获取可用汽车列表和按“制造”和“模式”分组的不可用汽车分支列表(例如:本田 Civid、福特 Escape)。因此,我认为您进行 2 个查询是正确的,但第二个查询似乎不正确。

第一个查询是您的第一个查询,它无法检索不可用的汽车。

第二个查询是通过'make'和'model'获取所有不可用的汽车组。这个查询看起来像:$nonavail = mysql_query("SELECT carID FROM reservations WHERE startDate = '".$sqlcoldate."' GROUP BY 'make', 'type'");

获得 2 个数组后,您可以正确操作并在布局上显示它们。请记住,第一个是可用的汽车,第二个是不可用的汽车分支。

于 2013-03-17T18:59:35.563 回答
0

此查询检查预订的开始日期或结束日期是否发生在新客户需要汽车的期间。它总结了可用的汽车。

SELECT c.model, ... ,
  SUM(
    CASE WHEN (r.startDate BETWEEN $desiredstart AND $desiredend) OR
              (r.endData BETWEEN $desiredstart AND $desiredend)  
         THEN 0
         ELSE 1 END) as num_available
FROM cars c 
  LEFT JOIN reservations r 
  ON (c.CarID=r.CarID)
WHERE
  r.deleted = 'no' (
    SELECT carID FROM reservations 
       WHERE 
         AND
 ) 
GROUP BY c.model
于 2013-03-12T18:33:47.063 回答