2011-08-03 80 views
0

前奏曲:我有一個大型數據集,其中有數十萬條記錄存儲在MySQL數據庫中。大大簡化了,每行都有一個日期時間字段來存儲打電話的日期和時間,以及一個整數字段來存儲呼叫的長度。PHP中的日期匹配和插值


方案:我忙着寫在PHP的內插函數,它產生一系列由預先計算的間隔所分離的日期。每個生成的日期都存儲在一個關聯數組中,並將日期用作鍵,並將每個值初始化爲0.然後,腳本向數據庫查詢記錄列表,並嘗試將日期時間記錄與預定義日期中的最近日期進行匹配,生成關聯數組。當找到最接近的匹配時,它只是將呼叫持續時間添加到該索引處數組的現有值。所生成的關聯數組


實施例:

$array = array( "2011-01-01 09:00:00" => 0, 
         "2011-01-01 09:30:00" => 0, 
         "2011-01-01 10:00:00" => 0, 
         "2011-01-01 10:30:00" => 0, 
         "2011-01-01 11:00:00" => 0, 
         "2011-01-01 11:30:00" => 0, 
         "2011-01-01 12:00:00" => 0 
        ) 

在上述例子中,使用30分鐘的間隔中產生日期範圍。


的從MySQL數據庫中的記錄例:

+---------------------+----------+ 
| datetime   | duration | 
+---------------------+----------+ 
| 2011-01-01 09:02:26 |  1 | 
| 2011-01-01 09:14:51 |  1 | 
| 2011-01-01 10:40:33 |  549 | 
| 2011-01-01 11:10:27 |  38 | 
| 2011-01-01 11:31:50 |  82 | 
+---------------------+----------+ 

每個這些記錄現在需要匹配於從上面給出的預先產生的陣列最接近日期時間鍵和添加的duration值到現有的匹配值。


問題: 這是很容易構建兩個嵌套for遍歷從數據庫中記錄interate然後線性通過關聯數組運行找到匹配,但這是效率非常低,並且成爲問題對於大數據集(想想bubblesort,這就是大致等價的)。稍微好一點的方法是線性循環來自數據庫的記錄,然後將數組作爲二叉樹遍歷,這當然更有效,並且可能是因爲兩個數組按時間順序排序。


問題: 是否有處理比我怎麼在上述問題中描述這個日期匹配更有效的方式?

+0

如果兩個列表均按日期/時間排序,則可以使用合併。像mergesort一樣:http://en.wikipedia.org/wiki/Merge_sort – Erik

回答

3

那麼將日期的UNIX_TIMESTAMP()除以30 * 60秒(30分鐘),並使用ROUND()作爲整數。然後,使用GROUP BY對它們進行分組,最後使用SUM()來計算持續時間。

SELECT SUM(duration), ROUND(UNIX_TIMESTAMP(datetime)/(30 * 60)) FROM table GROUP BY ROUND(UNIX_TIMESTAMP(datetime)/(30 * 60)) 
+0

雖然我沒有這樣做,但我仍然接受你的答案,因爲它給了我一個工作的基礎。我的實現在PHP中,並對您的建議執行類似的計算。 –

1

您當前的算法(如果我理解正確的話)是這樣的:

  1. 獲取所有記錄
  2. 每條記錄​​的日期時間進行比較,以數組鍵
  3. Incremement的總和基於記錄的適當陣列值

更有效的方法可以是:

  1. 查詢的持續時間爲給定時間的子集相匹配
  2. 插入的總和與合適的密鑰

這允許MySQL來提供優化的數學邏輯和陣列中的所有記錄的總和減少腳本所需的數組迭代次數。您將增加數據庫查詢的數量,但基準測試會告訴您折衷是否值得。