2011-03-23 86 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 | 
+------------+----------+----------+------+