2011-03-23 11 views
6

Tengo una tabla que contiene los resultados agregados con marcas de tiempo - lo que significa cada resultado por unidad de tiempo es el total hasta el momento:MySQL - encontró diferencia entre las filas de la misma tabla

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 

Estoy tratando de formular una consulta que tendra los deltas entre cada intervalo de tiempo:

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 
... 

De modo que cada fila por cada agrupación de fecha/IP resta el anterior (o 0). ¿Alguna manera simple de hacer esto? Gracias.

+0

Es posible que desee dar más detalles sobre cómo se maneja el cambio de fecha. ¿El resultado comienza desde cero todos los días o comienza desde cero solo al comienzo del archivo? – vbence

+0

¿Qué sucede si hay un punto de datos a las 11:00 y no hay 10:00, solo 09:00 o ninguno antes de ese día? –

Respuesta

10

Aquí es una solución sin variables. Supongo que tiene sus datos initail en una tabla llamada 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 

Aquí tenemos el valor anterior con una subselección (la máxima result de las marcas de tiempo anteriores de la misma ip). IFNULL nos da un 0 si este fue el primer valor, por lo que los resultados iniciales se muestran correctamente.

también recomiendo añadiendo el siguiente índice de thetable:

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

Buena solución, más eficiente. – Devart

+0

Gracias. Tenía un pequeño problema con el manejo del campo 'date'. Ahora esta bien. – vbence

+0

Tuve algunos problemas también, con variables;) – Devart

4

prueba este -

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 | 
+------------+----------+----------+------+ 
Cuestiones relacionadas