I have a table containing aggregated results with timestamps - meaning each result per time is the total so far:
我有一个包含带时间戳的聚合结果的表 - 这意味着每次每个结果是到目前为止的总数:
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
I'm trying to formulate a query that'll get the deltas between each time range:
我正在尝试制定一个查询,它将获得每个时间范围之间的增量:
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
...
So each row per date / ip grouping subtracts the one before it (or 0). Any simple way to do this? thanks.
因此每个日期/ ip分组的每一行都会减去它之前的那一行(或0)。有什么简单的方法吗?谢谢。
2 个解决方案
#1
10
Here is a solution without variables. I assume you have your initail data in a table called thetable
.
这是一个没有变量的解决方案。我假设你在一个名为thetable的表中有你的initail数据。
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
Here we get the previous value with a subselect (the maximal result
of the preceding timestamps from the same ip
). IFNULL
gives us a 0 if this was the first value, so initial results are displayed correctly.
这里我们通过subselect获取前一个值(来自同一ip的前一个时间戳的最大结果)。如果这是第一个值,IFNULL给出0,因此初始结果显示正确。
I also recommend adding the following index to thetable
:
我还建议在表格中添加以下索引:
CREATE INDEX sort1 ON thetable (ip, date, time);
#2
4
Try this one -
试试这个 -
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:=@f_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:=@s_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 |
+------------+----------+----------+------+
#1
10
Here is a solution without variables. I assume you have your initail data in a table called thetable
.
这是一个没有变量的解决方案。我假设你在一个名为thetable的表中有你的initail数据。
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
Here we get the previous value with a subselect (the maximal result
of the preceding timestamps from the same ip
). IFNULL
gives us a 0 if this was the first value, so initial results are displayed correctly.
这里我们通过subselect获取前一个值(来自同一ip的前一个时间戳的最大结果)。如果这是第一个值,IFNULL给出0,因此初始结果显示正确。
I also recommend adding the following index to thetable
:
我还建议在表格中添加以下索引:
CREATE INDEX sort1 ON thetable (ip, date, time);
#2
4
Try this one -
试试这个 -
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:=@f_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:=@s_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 |
+------------+----------+----------+------+