0

我有这个查询:

SELECT  price.car_number1, car_from, car_to, car_fares
FROM    price, car
WHERE   car.car_number1 = price.car_number1

输出如下所示:

car_number1    car_from     car_date      car_fare
------------------------------------------------------
BAL2018        2013-01-21   2013-01-26    $555         
BAL2018        2013-01-27   2013-01-28    $111
BAL2019        2013-01-26   2013-01-27    $211 
BAL2020        2013-01-26   2013-01-27    $545

2013-01-21现在假设在从to的费率的 UI 结果中使用希望2013-01-28,我想以某种或其他方式打印每辆车在各自日期的价格,并且如果汽车没有分配票价,它应该显示为N/A

请让我知道我是否可以在 mysql 或任何 PHP 中执行此操作

我想让它看起来像这样(如示例)

           01-21   01-22 01-23 01-24 01-25  01-26 01-27 01-28 
 BAL2018   $555    $555  $555  $555  $555   $555  $111  $111
 BAL2019   N/A     N/A   N/A   N/A   N/A    $211  $211  N/A
4

3 回答 3

0

In the example below calendar is a simple utility table holding all dates that could ever be required. Personally, I'd most likely handle the missing values and, certainly, the pivoting at the application level, for ease of scalability.

DROP TABLE IF EXISTS fares;

CREATE TABLE fares
( vehicle_id VARCHAR(12) NOT NULL 
, fare_start DATE NOT NULL
, fare_end DATE NULL
, fare DECIMAL(5,2) NOT NULL 
, PRIMARY KEY(vehicle_id,fare_start)
);

INSERT INTO fares VALUES 
('BAL2018','2013-01-21','2013-01-26',555.00),
('BAL2018','2013-01-27','2013-01-28',111.00),
('BAL2019','2013-01-26','2013-01-27',211.00), 
('BAL2020','2013-01-26','2013-01-27',545.00);

DROP TABLE IF EXISTS vehicles;

CREATE TABLE vehicles
(vehicle_id VARCHAR(12) NOT NULL PRIMARY KEY
,description VARCHAR(12) NOT NULL
);

INSERT INTO vehicles VALUES 
('BAL2018','vehicle01'),
('BAL2019','vehicle02'),
('BAL2020','vehicle03');

SELECT * FROM calendar WHERE dt BETWEEN '2013-01-20' AND '2013-01-28';
+------------+
| dt         |
+------------+
| 2013-01-20 |
| 2013-01-21 |
| 2013-01-22 |
| 2013-01-23 |
| 2013-01-24 |
| 2013-01-25 |
| 2013-01-26 |
| 2013-01-27 |
| 2013-01-28 |
+------------+

 SELECT c.dt,v.vehicle_id,f.fare_start,f.fare_end,f.fare FROM calendar c
   JOIN vehicles v
   LEFT
   JOIN fares f
     ON f.vehicle_id = v.vehicle_id
    AND c.dt BETWEEN f.fare_start AND f.fare_end
  WHERE c.dt BETWEEN '2013-01-20' AND '2013-01-28';
+------------+------------+------------+------------+--------+
| dt         | vehicle_id | fare_start | fare_end   | fare   |
+------------+------------+------------+------------+--------+
| 2013-01-20 | BAL2018    | NULL       | NULL       |   NULL |
| 2013-01-20 | BAL2019    | NULL       | NULL       |   NULL |
| 2013-01-20 | BAL2020    | NULL       | NULL       |   NULL |
| 2013-01-21 | BAL2018    | 2013-01-21 | 2013-01-26 | 555.00 |
| 2013-01-21 | BAL2019    | NULL       | NULL       |   NULL |
| 2013-01-21 | BAL2020    | NULL       | NULL       |   NULL |
| 2013-01-22 | BAL2018    | 2013-01-21 | 2013-01-26 | 555.00 |
| 2013-01-22 | BAL2019    | NULL       | NULL       |   NULL |
| 2013-01-22 | BAL2020    | NULL       | NULL       |   NULL |
| 2013-01-23 | BAL2018    | 2013-01-21 | 2013-01-26 | 555.00 |
| 2013-01-23 | BAL2019    | NULL       | NULL       |   NULL |
| 2013-01-23 | BAL2020    | NULL       | NULL       |   NULL |
| 2013-01-24 | BAL2018    | 2013-01-21 | 2013-01-26 | 555.00 |
| 2013-01-24 | BAL2019    | NULL       | NULL       |   NULL |
| 2013-01-24 | BAL2020    | NULL       | NULL       |   NULL |
| 2013-01-25 | BAL2018    | 2013-01-21 | 2013-01-26 | 555.00 |
| 2013-01-25 | BAL2019    | NULL       | NULL       |   NULL |
| 2013-01-25 | BAL2020    | NULL       | NULL       |   NULL |
| 2013-01-26 | BAL2018    | 2013-01-21 | 2013-01-26 | 555.00 |
| 2013-01-26 | BAL2019    | 2013-01-26 | 2013-01-27 | 211.00 |
| 2013-01-26 | BAL2020    | 2013-01-26 | 2013-01-27 | 545.00 |
| 2013-01-27 | BAL2018    | 2013-01-27 | 2013-01-28 | 111.00 |
| 2013-01-27 | BAL2019    | 2013-01-26 | 2013-01-27 | 211.00 |
| 2013-01-27 | BAL2020    | 2013-01-26 | 2013-01-27 | 545.00 |
| 2013-01-28 | BAL2018    | 2013-01-27 | 2013-01-28 | 111.00 |
| 2013-01-28 | BAL2019    | NULL       | NULL       |   NULL |
| 2013-01-28 | BAL2020    | NULL       | NULL       |   NULL |
+------------+------------+------------+------------+--------+

27 rows in set (0.00 sec)

于 2013-01-27T01:13:06.447 回答
0

只是在没有实际数据的情况下猜测,但是像这样?

SELECT  car.car_number1, car.car_from, car.car_to, 
            ifnull(price.car_fares,'N/A') as car_fare
FROM    car left join price ON car.car_number1=price.car_number1
WHERE   car.car_from >= '2013-01-21' and car.car_to < '2013-01-28'

我假设该car_fares字段在price表中,所有其他字段都在car表中。

于 2013-01-26T09:53:07.860 回答
0

恕我直言,最好的折衷方案是在 MySQL 中选择日期范围,然后使用 PHP 提供任何缺失的信息。

请原谅我可能过于挑剔,但有一次我被以下所有问题所困扰,所以我将为一个看似简单的问题提供一个显然复杂的解决方案:-)

日期选择算法可能会出现一个问题,因为“第二天”并不是人们想象的那么明确的表达方式——当切换夏令时时,有些日子是 23 小时或 25 小时,有些日子有额外的一秒钟,以便 $ts += 86400 将您从 D:M:Y 00:00:00 带到 D:M:Y 23:59:59 而不是 D+1:M:Y 00:00:00。

直到您在 7 月(或者是 6 月?)因为闰秒而失去 15 个酒店房间预订之前,这似乎很挑剔。这不是我的代码,但我是必须进行清理的人。

另一个问题是,如果您有“1 月 1 日”的 CAR_FROM 和“12 月 31 日”的 CAR_TO,并且您想要 3 月 21 日至 28 日之间的价格,那么该行将是相关的,即使没有行指定 3 月的日期. 所以你需要注意重叠。

最后,您可能有一个从 1-1-2013 到 31-12-2013 的条目,然后您可能有一个从 2013 年 5 月 1 日到 2013 年 5 月 17 日的条目,并且您希望第二个条目优先于5 月 1 日至 17 日的范围。实际上,如果客户改变主意,您需要一种快速从一个优先系统选择到另一个系统的方法。

所以你可以这样做:

<?php

    $start = mktime(12, 0, 0, $month1, $day1, $year1);
    $stop  = mktime(12, 0, 0, $month2, $day2, $year2);

    $DATE_FORMAT = 'd-m-Y'; // This might be a define, actually

    // Use these dates in MySQL query. This takes care
// of most date problems.

    $SQL_From = date('Ymd000000', $start);
    $SQL_To   = date('Ymd235959', $stop);

    // We create a date array initialized with N/A, and use
    // a date format as a key
$empty = array();
    for ($ts = $start; $ts <= $stop; $ts += 86400)
    {
        $date = date($DATE_FORMAT, $ts);
        $empty[$date] = 'N/A';
    }

/*
To select dates overlapping [FROM-TO], consider that we do NOT want
a date when its TO is less than our FROM of interest:
    [from -- car -- to]   [FROM     TO]
and neither when its from is more than our TO of interest:
    [FROM     TO] [from -- car -- to]  
So we want all dates except those, and this means
    WHERE NOT ( car_to < SQL_From OR car_from > SQL_To)

But since NOT (A OR B) is logically equal to A AND B, we get this
not very intuitive, but very efficient query

    $query = ...
SELECT  price.car_number1, car_from, car_to, car_fares
FROM    price JOIN car ON car.car_number1 = price.car_number1
WHERE   car_from < $SQL_To AND car_to > $SQL_From
ORDER BY car_number1, car_from;

    The precedence is given by car_from: later dates win over earlier dates.
    But you might have a PRIORITY field that overrides all, so that PRIORITY=0
    means normal and PRIORITY 99 means "THESE are the prices, damn your eyes!";
    to achieve that, you can now simply "ORDER BY car_number1,priority,car_from."

*/

$cars = array();

// Now we retrieve all car data, with PDO or whatever

while($tuple = SQLFetchRow(...))
{
    // If this is a new car, we initialize its array to all N/A

    if (!isset($cars[$tuple['car_number1']))
        $prices = $empty;
    else
        $prices = $cars[$tuple['car_number1'];

    // Now we check our tuple and see what prices have changed
    // MySQL retrieves date in Y-M-D format

    list($y,$m,$d)  = explode('-', $tuple['car_from']);
    $from       = mktime(12, 0, 0, $m, $d, $y);
    list($y,$m,$d)  = explode('-', $tuple['car_to']);
    $to     = mktime(12, 0, 0, $m, $d, $y);

    // This will overwrite any existing data with fresher data
        for ($ts = $from; $ts <= $to; $ts += 86400)
        {
            $date = date($DATE_FORMAT, $ts);
            $prices[$date] = $tuple['car_fare'];
        }

    // Now we save the modified array into $cars.
    $cars[$tuple['car_number1'] = $prices;
}

// And finally we print the results into a variable,
    // so it will be easier to wrap this into a helper function.

$row = '<tr>';
$row .= '<th>-</th>';
foreach($empty as $date => $dummy)
    $row = '<th>'.$date.'</th>';
$row .= '</tr>';

$table  = '<table>' . $row;

foreach($cars as $plate => $prices)
{
    $row = '<tr><td>'.$plate.'</td>';
    foreach($prices as $dummy_date => $price)
        $row .= '<td>'.$price.'</td>';
    $row .= '</tr>';

    $table .= $row;
}
$table  .= '</table>';

print $table;
?>
于 2013-01-26T10:40:27.480 回答