2017-02-17 14 views
0

昨天有人询问哪一个需要使用LAG更新MySQL表。考虑下面的输入表(左),以及所需的输出(右):在更新过程中在MySQL中模拟LAG

**INPUT**         **OUTPUT** 
ID TestDate PerformanceStatus (PS) ID TestDate PS PreviousPerformanceStatus 
1 15/03/2016 0       1 15/03/2016 0 0 
1 01/04/2016 2       1 01/04/2016 2 0 
1 05/05/2016 1       1 05/05/2016 1 2 
1 07/06/2016 1       1 07/06/2016 1 1 
2 15/03/2016 0       2 15/03/2016 0 1 
2 01/04/2016 2       2 01/04/2016 2 0 
2 05/05/2016 1       2 05/05/2016 1 2 
2 07/06/2016 3       2 07/06/2016 3 1 
2 23/08/2016 1       2 23/08/2016 1 3 

换句话说,我们的目标是要分配给PreviousPerformanceStatus这在来之前记录存在的价值,通过ID作为排序则TestDate

由@ spencer7593给出的接受答案使用了相关的子查询。但是,首先突然想到的是使用用户变量。这里是我回答:

SET @lag = 0; 
UPDATE yourTable 
SET PreviousPerformanceStatus = @lag, 
    @lag:=PerformanceStatus 
ORDER BY ID, TestDate 

有人告诉我,这个答案是不稳定的,但我想知道,如果有人可以解释为什么事情可能出错,你会在这种情况下可以发生的,最后什么事情我们在这里使用用户变量来模拟LAG。

这是我的理解,下面SELECT查询就没有问题可言:

SELECT PerformanceStatus, 
     @lag AS PreviousPerformanceStatus, 
     @lag:=PerformanceStatus 
FROM yourTable 
ORDER BY ID, TestDate 

但是,这样做时UPDATE有其他方面的考虑考虑。

+0

更新语句抛出一个1064错误,所以这个问题有点没有意义。 –

+0

@ P.Salmon有什么方法可以解决这个错误? –

+0

错误是, @lag:= PerformanceStatus,我不认为你可以在更新语句中设置变量 - 所以不。 –

回答

1

我不认为你可以在更新语句中设置变量。 这里是我的reasoning- 鉴于这种

drop table if exists t; 

create table t (ID int, TestDate date, PerformanceStatus int, previousperformancestatus int); 
insert into t values 
(1 , '2016-03-15' , 0, null),       
(1 , '2016-04-01' , 2, null),       
(1 , '2016-05-05' , 1, null),       
(1 , '2016-06-07' , 1, null),       
(2 , '2016-03-15' , 0, null),       
(2 , '2016-04-01' , 2, null),       
(2 , '2016-05-05' , 1, null),       
(2 , '2016-06-07' , 3, null),       
(2 , '2016-08-23' , 1, null) 
; 

此代码失败

MariaDB [sandbox]> SET @lag = 0; 
Query OK, 0 rows affected (0.00 sec) 

MariaDB [sandbox]> UPDATE T 
    -> SET previousPerformanceStatus = @lag , 
    ->  @lag:=PerformanceStatus 
    -> ORDER BY ID, TestDate; 
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '@lag:=PerformanceStatus 
ORDER BY ID, TestDate' at line 3 

注释掉@lag:= PerformanceStatus 此代码运行

MariaDB [sandbox]> SET @lag = 0; 
Query OK, 0 rows affected (0.00 sec) 

MariaDB [sandbox]> UPDATE T 
    -> SET previousPerformanceStatus = @lag 
    -> #,@lag:=PerformanceStatus 
    -> ORDER BY ID, TestDate; 
Query OK, 0 rows affected (0.01 sec) 
Rows matched: 9 Changed: 0 Warnings: 0 

由于代码没有错误至少运行和手册https://dev.mysql.com/doc/refman/5.7/en/update.html指出“SET子句指出要修改哪些列”我对此的看法是你可以没有在更新语句中设置变量,因此使用此方法不可能模拟滞后。

+0

感谢您的研究。如果您希望强烈需要使用DML查询的分析函数,那么这可能会避免MySQL。 –