计算在预定义日期范围之间的天数

时间:2011-02-23 17:50:02

标签: php mysql algorithm sql-optimization

这是一个复杂的情况。我有预订系统预订房间。

事情是房间的价格不是作为单一价值存储,而是基于期间。就像一个房间在9月到12月之间可以有一个每日房价,从3月到8月可以有不同的房价,而其他房价则是基本房价。

费率表是这样的:

ROOMID | RATE | PERIOD_START | PERIOD_END

让我们假设3月1日至3月31日期间的房价为20美元/天,4月15日至5月30日期间房价为30美元,此外房价为15美元的固定房价。 /天。

如果这个房间是由一位客户在3月15日至5月10日之间预订的,则总费用为:

15th March - 31st march charged at 20 Dollars/day = 16x20
1st April - 14th April charged at 15 Dollars/day = 14x15
15th April - 10th May charged at 30 Dollars/day = 25x30

现在我如何在代码中计算这个值,我需要根据费率周期计算天数,否则使用基本费率。它很复杂,但就是这样。我正在使用php MySQL

5 个答案:

答案 0 :(得分:2)

这是一种可行的解决方案算法:

  1. 查找与预订期间具有非空交叉点的所有费率期间
  2. 对于(1)中找到的每个费率期间,计算与预订期间的交叉点的天数,并乘以期间的费率
  3. 剩余天数(即预订期限的天数,减去(2)中所有天数的总和,是您的基准天数
  4. 重新(1),为了找出与预订期间相关的费率期间,请注意,(A,B)(C,D)的两个时间间隔iff D < A or C > B有一个空的交集,所以你可以否定这种情况。应该看起来像:

    SELECT * FROM rates 
       WHERE NOT (booking_end < period_start OR 
                  booking_start > period_end)
    

    Re(2),您只需要找到max(booking_start, period_start)min(booking_end, period_end)之间的天数,包括在内。我确信有处理日期的工具,但在最坏的情况下,你可以循环使用它。

    很抱歉,但我不是编写实际代码的SQL / php向导... :)

答案 1 :(得分:1)

一个可能的解决方案是建立一个名为price_periods的表,其中包含开始日期,结束日期和价格以及对房间的引用。

所以SQL表看起来像这样。

PRICE_PERIODS

PPID | ROOM_ID | PP_START_DATE | PP_END_DATE | PP_PRICE
-------------------------------------------------------
1      2         09-20           10-20         15
2      2         10-21           11-20         20

然后您只需计算预订的日期,因此假设A人希望从10-11到10-25租用房间,他必须支付ID为1的PRICE_PERIOD,直到PP_END_DATE发生然后支付ID为2的PRICE_PERIOD,直到预订结束。所以事情是你可能总是有两个以上的约会日期。

我想您的预订表看起来像这样。

BOOKINGS

B_ID | ROOM_ID | USER_ID | START_DATE | END_DATE
------------------------------------------------
1      2         4         10-11        10-25

你必须进行计算,但有一个可能有效的开始。

答案 2 :(得分:1)

试试这个。

这会在预订期间的每一天循环,从表中找到适当的费率,然后将其添加到总数中。

$Day="2011-03-15";
$End="2011-05-10";
$Periods=array(); // Filled with the Mysql rows - mysql_fetch_assoc()
$Total=0;

修改

更优化。

foreach($Periods as $Period) {
    if($Day>=$Period['PERIOD_START']&&$Day<=$Period['PERIOD_END']) {
        while($Day<=$End&&$Day<=$Period['PERIOD_END']) {
            $Total+=$Period['RATE'];
            $Day=date('Y-m-d',strtotime("$Day +1 day"));
        }
    }
}

答案 3 :(得分:1)

这里只有半个严肃的答案。

如果您想要单个SQL查询,则可以执行以下操作:

SELECT SUM(IF(ISNULL(r.rate), 10, r.rate))
FROM days AS d
LEFT JOIN rates AS r ON d.d BETWEEN r.start AND r.end
  WHERE d.d BETWEEN '2011-03-15' and '2011-05-10';

诀窍是你需要一个名为“days”的表,它有一个日期字段d。预先填充该表以包括从现在到永恒的每一天。通过脚本很容易做到;你只需要保留未来可预订的日期。

请注意,您必须注意选择开始日期和结束日期的方式。例如,如果您在3月31日到4月1日之间预订房间,那究竟是什么意思?

那是一天20美元一天10美元吗?或者只需要20美元一天?或者单日10美元?

它本身并没有真正影响这个答案,但它确实会影响您构建费率表的方式以及您用作开始和停止的日期。

此外,此版本假设费率字段使用完整的YYYY-MM-DD格式。这不是绝对的要求,但如果它只是MM-DD,那么你必须稍微修改连接。

就个人而言,我不会这样做。相反,我只是使用DateInterval类在PHP代码中循环,并以这种方式查询价格。

答案 4 :(得分:1)

在PHP中,您可以在两个日期之间使用DateTimecalculate the difference间隔。