Como faço para atrasar colunas no MySQL?

Considere a seguinte tabela:

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

A coluna id é auto-incrementada, mas contém lacunas. A coluna de value é numérica.

Eu quero olhar para o aumento do value longo do tempo, definindo o value em relação ao value duas linhas acima. Isso é para a linha id=85 Eu quero definir o value da linha id=85 (546) em relação ao value da linha id=27 (334). O valor a ser computado para a linha id=85 é, portanto, 546/334 = 1,63473.

Este é o resultado que quero alcançar:

 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) +-----+---------+---------------------+ 

Como eu executo esse atraso no MySQL?

Por favor, note que a coluna id contém lacunas, então simplesmente entrar na mesma tabela com t1.id = t2.id - 2 não funcionará.

Aqui está uma solução que retorna o que você quer no MySQL

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

O MySQL 5.1 não gosta de uma self join contra uma subconsulta, então você tem que contar as linhas duas vezes, por isso não é tão arrumado ou escalável como pode ser, mas torna a especificação do lag simples.

Para os leitores que usam o Oracle, isso é muito mais fácil

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

Como existem apenas duas linhas entre a atual e a outra de onde você deseja obter os dados ‘históricos’, você poderia usar as variables ​​para armazenar os dados temporariamente usando algo como:

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

É uma solução muito desordenada, mas acho que vai fazer o trabalho. Talvez haja alguma maneira de impedir que as variables ​​sejam exibidas, eu não olhei tão longe.

Intereting Posts