2011-03-23 50 views
6

我有一個包含時間戳彙總結果的表之間的差異 - 這意味着每一次每一個結果是總到目前爲止:MySQL的 - 找到相同的錶行

date  | time | ip  | result 
--------------------------------------- 
2011-03-01 | 10:00 | 10.0.0.1 | 200 
2011-03-01 | 11:00 | 10.0.0.1 | 303 
2011-03-01 | 12:00 | 10.0.0.1 | 415 
2011-03-01 | 13:00 | 10.0.0.1 | 628 
2011-03-01 | 10:00 | 10.0.0.2 | 198 
2011-03-01 | 11:00 | 10.0.0.2 | 234 
2011-03-01 | 12:00 | 10.0.0.2 | 373 
2011-03-01 | 13:00 | 10.0.0.2 | 512 

我試圖制定一個查詢,將獲得每個時間範圍之間的增量:

date  | time | ip  | diff 
--------------------------------------- 
2011-03-01 | 10:00 | 10.0.0.1 | 200 
2011-03-01 | 11:00 | 10.0.0.1 | 103 
2011-03-01 | 12:00 | 10.0.0.1 | 112 
2011-03-01 | 13:00 | 10.0.0.1 | 213 
2011-03-01 | 10:00 | 10.0.0.2 | 198 
2011-03-01 | 11:00 | 10.0.0.2 | 36 
2011-03-01 | 12:00 | 10.0.0.2 | 139 
2011-03-01 | 13:00 | 10.0.0.2 | 139 
... 

所以每日期/ IP分組中的每個行中減去一個前(或0)。 任何簡單的方法來做到這一點?謝謝。

+0

你可能想闡述的日期改變是如何處理的。結果是每天從零開始,還是從文件開頭的零開始? – vbence 2011-03-23 10:53:09

+0

如果有一個11:00數據點並且沒有10:00,那麼在那天只有09:00或者沒有一個呢? – 2011-03-23 11:38:46

回答

10

這裏是不變量的解決方案。我假設你有一個名爲thetable的表的初始化數據。

SELECT date, time, ip, 
    result - IFNULL((
     SELECT MAX(result) 
     FROM thetable 
     WHERE ip = t1.ip 
     AND (date < t1.date 
      OR date = t1.date AND time < t1.time) 
    ) , 0) AS diff 
FROM thetable AS t1 
ORDER BY ip, date, time 

在這裏,我們得到一個子查詢(前面的時間戳來自同一ip最大result)以前的值。 IFNULL給了我們一個0,如果這是第一個值,所以初始結果顯示正確。

我還建議增加以下指標thetable

CREATE INDEX sort1 ON thetable (ip, date, time); 
+0

好的解決方案,更高效。 – Devart 2011-03-23 11:01:53

+0

謝謝。它在處理'date'字段時遇到了一些問題。現在可以了。 – vbence 2011-03-23 11:17:21

+0

我也有一些麻煩,變量;) – Devart 2011-03-23 11:30:23

4

嘗試這一個 -

SET @f_rank = 0; 
SET @s_rank = 0; 
SET @f_date = NULL; 
SET @f_ip = NULL; 
SET @s_date = NULL; 
SET @s_ip = NULL; 
SELECT t1.date, t1.time, t1.ip, IF(t2.result IS NULL, t1.result, t1.result - t2.result) diff FROM 
    (SELECT *, IF(@f_date = date AND @f_ip = ip, @f_rank:[email protected]_rank + 1, @f_rank:=1) AS rank, @f_date := date, @f_ip := ip FROM table1 ORDER BY date, ip, time) t1 
    LEFT JOIN 
    (SELECT *, IF(@s_date = date AND @s_ip = ip, @s_rank:[email protected]_rank + 1, @s_rank:=1) AS rank, @s_date := date, @s_ip := ip FROM table1 ORDER BY date, ip, time) t2 
    ON t1.date = t2.date AND t1.ip = t2.ip AND (t1.rank = t2.rank + 1); 

+------------+----------+----------+------+ 
| date  | time  | ip  | diff | 
+------------+----------+----------+------+ 
| 2011-03-01 | 10:00:00 | 10.0.0.1 | 200 | 
| 2011-03-01 | 11:00:00 | 10.0.0.1 | 103 | 
| 2011-03-01 | 12:00:00 | 10.0.0.1 | 112 | 
| 2011-03-01 | 13:00:00 | 10.0.0.1 | 213 | 
| 2011-03-01 | 10:00:00 | 10.0.0.2 | 198 | 
| 2011-03-01 | 11:00:00 | 10.0.0.2 | 36 | 
| 2011-03-01 | 12:00:00 | 10.0.0.2 | 139 | 
| 2011-03-01 | 13:00:00 | 10.0.0.2 | 139 | 
+------------+----------+----------+------+