2011-02-23 136 views
2

這是一個複雜的情況,我是ain。我有預訂房間的預訂系統。計算預定義日期範圍內的天數

事情是房間的價格不是作爲一個單一的價值儲存,而是以期間爲基礎。就像一個房間可以在九月到十二月之間有一個每日房價,並且在三月到八月之間可以有一個不同的房價,而另一個房間的基本房價則可以。

率表是這樣的:

ROOMID | RATE | PERIOD_START | PERIOD_END 

讓我們假設對於到3月31日3月1日之間的房,價格爲20元/天,並於5月30日同處一室,從4月15日率是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

+0

[SQL要檢查一組日期是否在指定的日期範圍內](http://stackoverflow.com/questions/5027119/sql-to-check-if-a-set-of-日期 - 落在指定範圍內的日期)[或者,也許這個](http://stackoverflow.com/questions/5092028/need-to-see-if-a-range-of-dates-重疊 - 另一個日期範圍內的SQL) – 2011-02-23 17:53:10

+0

所以問題是,有些日子要被預訂可能在不同的價格/日期範圍?那麼就像3月31日之前的3天,然後4月1日之後的兩天? – Jonah 2011-02-23 18:00:07

+0

@jonah - yep就像你放的那樣 – Ali 2011-02-23 18:04:52

回答

2

這是一種可能的解決方案的算法:

  1. 找到具有與(1)中,計算所找到的每個速率週期的預訂期間
  2. 非空交集所有速率週期與預訂期限相交的天數,並乘以期間費率
  3. 剩餘天數(即以天爲單位的預訂期限減去(2)中找到的所有天數之和即爲您的基本費率天數

的Re(1),以便找到哪個速率週期相交預訂期間,請注意,2個間隔(A,B)(C,D)有一個空交集IFF D < A or C > B,這樣可以只是否定該條件。應該是這個樣子:

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

回覆(2),你只需要找到max(booking_start, period_start)min(booking_end, period_end),(含)之間的天數。我確信有公用事業來處理日期,但最壞的情況下,你可以循環。

很抱歉,但我不是一個SQL/PHP的嚮導來編寫實際的代碼... :)

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 

,那麼只需在計算具體日期預訂已通過取得,因此假設該人想租從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 

你將不得不作出的計算,但有一個開始,將可能工作。

1

試試這個。

這將循環顯示在預訂時間段內的每一天,從表中找到適當的速率,然後將其添加到總計中。

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

EDIT

更多優化。

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")); 
     } 
    } 
} 
+0

If你想優化它,你並不需要在每次迭代中逐步完成每個週期。只要保持排序的時間段,並且當您經過當前時間段時,切換到下一個時段。如果'$ < $period->開始',您將知道是否處於期間($ 10)之間。 – Matthew 2011-02-23 22:26:47

+0

通過將Periods循環放在頂部來更好地進行優化。這減少了整個不必要的循環。 – 2011-02-23 22:56:59

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'; 

的技巧是,你需要一個所謂的「天」,有一個單獨的日期字段d表。預先填充該表格以便從現在開始直到永恆。通過腳本很容易做到;你只需要在那裏保留未來的可預約日期。

請注意,您必須小心如何選擇開始日期和結束日期。例如,如果您在3月31日至4月1日之間預訂了房間,那究竟意味着什麼?

這是一個20美元的日子和一個10美元的日子嗎?或者只有20美元一天?還是單日10美元?

它本質上並不影響這個答案,但它確實會影響您建立費率表的方式以及您用作啓動和停止的日期。

此外,此版本假定rates字段使用完整的YYYY-MM-DD格式。這不是絕對的要求,但如果它只是MM-DD,那麼你必須稍微修改連接。

個人而言,我不會這樣做。相反,我只是在使用DateInterval類的PHP代碼中循環使用這些日子,並以這種方式查詢價格。