2011-03-30 25 views
9

Considérese la siguiente tabla:¿Cómo puedo retrasar las columnas en MySQL?

SELECT id, value FROM table ORDER BY id ASC; 
+-----+---------+ 
| id | value | 
+-----+---------+ 
| 12 | 158  | 
| 15 | 346  | 
| 27 | 334  | 
| 84 | 378  | 
| 85 | 546  | 
+-----+---------+ 

La columna id es auto-incrementales pero contiene huecos. La columna value es numérica.

Quiero mirar por el aumento de value lo largo del tiempo mediante el establecimiento de value en relación con los value dos filas anteriores. Eso es para la fila id=85 Quiero establecer el value de la fila id=85 (546) en relación con el value de la fila id=27 (334). El valor que se calculará para la fila id=85 es 546/334 = 1.63473.

Este es el resultado que quiero lograr:

SELECT id, value, ...; 
+-----+---------+---------------------+ 
| id | value | value/lag(value, 2) | (the syntax value/lag(value, 2) is made up) 
+-----+---------+---------------------+ 
| 12 | 158  | NULL    | 
| 15 | 346  | NULL    | 
| 27 | 334  | 2.11392    | (334/158=2.11392) 
| 84 | 378  | 1.09248    | (378/346=1.09248) 
| 85 | 546  | 1.63473    | (546/334=1.63473) 
+-----+---------+---------------------+ 

¿Cómo realizo tal retraso en MySQL?

Tenga en cuenta que la columna id contiene huecos, por lo que simplemente unir en la misma tabla con t1.id = t2.id - 2 no funcionará.

+0

Hay una función de retraso() en el estándar SQL, pero MySQL no soporta esto. –

Respuesta

9

Aquí es una solución que devuelva lo que quiere en MySQL

SET @a :=0; 
SET @b :=2; 
SELECT r.id, r.value, r.value/r2.value AS 'lag' 
FROM 
(SELECT if(@a, @a:[email protected]+1, @a:=1) as rownum, id, value FROM results) AS r 
LEFT JOIN 
(SELECT if(@b, @b:[email protected]+1, @b:=1) as rownum, id, value FROM results) AS r2 
ON r.rownum = r2.rownum 

MySQL 5.1 no le gusta un auto unirse contra una subconsulta por lo que tiene que contar filas dos veces, así que no es tan ordenado o escalable, ya que podría ser, pero hace que especificar el retraso sea simple.

Para los lectores que utilizan Oracle lugar esto es mucho más fácil

SELECT id, value, value/lag(value, 2) over (order by id) as lag from results; 
+3

* Para lectores que usan Oracle *: o PostgreSQL o DB2 o Teradata :) –

0

Como sólo hay dos filas entre la actual y la de la que desea obtener los datos 'históricos' ¿Podría Perphaps utilizar variables para almacenar los datos temporalmente usando algo como:

set @oldid0=999999;
set @oldid1=999999;
set @oldid2=999999;
select @oldid0:[email protected],@oldid1:[email protected],@oldid2:=id, value/@oldid0 from table order by id asc;

Es una solución muy desordenada, pero creo que hará el trabajo. Tal vez haya alguna manera de evitar que se muestren las variables, no he investigado tanto.

+0

Lag (2) es solo un ejemplo. Estoy buscando una solución general que permita decir Lag (365) :-) – knorv

+0

Ah, leí su pregunta y estúpidamente asumí que solo quería decir lag (2) – blankabout

Cuestiones relacionadas