2011-03-30 80 views
9

考慮下表:如何在MySQL中滯後列?

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

id列自動遞增,但包含的空白。 value列是數字。

我想看看value隨着時間的推移增加value相對於value上面的兩行。這是行id=85我想設置行id=85(546)的value相對於行id=27(334)的value。因此,對於行id=85計算的值因此是546/334 = 1.63473。

這是我想達到的效果:

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

如何在MySQL中執行這種滯後?

請注意,id列包含空位,因此只需加入與t1.id = t2.id - 2相同的表即可。

+0

有一個在SQL標準滯後()函數,但MySQL不支持這一點。 – 2011-03-30 07:40:33

回答

9

這裏是一個解決方案,返回你想在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中不喜歡自加入對一個子查詢,所以你必須兩次計算行,所以還不如整齊或可伸縮的,因爲它可能是,但它確實使得指定滯後簡單。

對於使用Oracle的讀者,而不是這是很容易

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

*對於使用Oracle *或PostgreSQL的讀者或DB2或Teradata :) – 2011-03-30 10:42:41

0

由於有當前之一,從那裏你想要得到的「歷史」數據可能你perphaps使用變量來存儲數據暫時使用的東西像一個之間只有兩排:

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;

這是一個非常不整潔的解決方案,但我認爲它會完成這項工作。也許有一些方法可以防止變量顯示出來,我還沒有看到它。

+0

滯後(2)只是一個例子。我正在尋找一個通用的解決方案,允許說滯後(365):-) – knorv 2011-03-30 09:50:30

+0

啊,我讀你的問題,愚蠢地認爲你只意味着lag(2) – blankabout 2011-03-30 10:25:55