2017-02-17 2 views
0

Gestern wurde eine interesting question gefragt, die eine Aktualisierung einer MySQL-Tabelle unter Verwendung der LAG erforderte. Betrachten Sie die folgende Eingabetabelle (links), und die gewünschte Ausgabe (rechts):LAG in MySQL während einer Aktualisierung simulieren

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

Mit anderen Worten, das Ziel zu PreviousPerformanceStatus den Wert, der in dem Datensatz, bevor er existiert zuzuweisen, wie befohlen durch ID dann TestDate.

Die akzeptierte Antwort von @ spencer7593 verwendete eine korrelierte Unterabfrage. Was mir jedoch zuerst in den Kopf kam, war die Verwendung einer Benutzervariablen. Hier ist, wie ich antwortete:

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

Ich wurde gesagt, dass diese Antwort nicht stabil ist, aber ich frage mich, ob jemand erklären könnte, warum etwas schief gehen könnte, was in diesem Fall geschehen würde, und schließlich, was könnte wir tun, um hier eine Benutzervariable zu verwenden, um LAG zu simulieren.

Es ist mein Verständnis, dass die folgende SELECT Abfrage überhaupt keine Probleme haben würde:

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

Wenn jedoch dabei ein UPDATE gibt es andere Überlegungen zu berücksichtigen.

+0

Die update-Anweisung löst einen 1064-Fehler, so dass die Frage ein bisschen strittig ist. –

+0

@ P.Salmon Gibt es eine Möglichkeit, den Fehler zu beheben? –

+0

Der Fehler ist an, @ Lag: = PerformanceStatus, ich glaube nicht, dass Sie Variablen in einer Update-Anweisung festlegen können - also nein. –

Antwort

1

Ich glaube nicht, dass Sie Variablen in einer Update-Anweisung setzen können. Hier ist meine reasoning- Vor diesem

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

Dieser Code schlägt fehl

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 

Kommentar aus @lag: = PerformanceStatus Dieser Code läuft

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 

Da Code zumindest läuft ohne Fehler und das Handbuch https://dev.mysql.com/doc/refman/5.7/en/update.html gibt an "Die SET-Klausel gibt an, welche Spalten geändert werden sollen" meine Annahme ist, dass Sie ca n Stellen Sie keine Variablen in einer Aktualisierungsanweisung ein, sodass die Simulation der Verzögerung mit dieser Methode nicht möglich ist.

+0

Danke für die Forschung. Dies ist ein Grund, vielleicht auf MySQL zu verzichten, wenn Sie einen starken Bedarf an analytischen Funktionen mit DML-Abfragen erwarten. –