2016-07-23 28 views
0

Ich habe vorher eine Frage zu How to get temporal sequence by mysql gestellt. Dort möchte ich eine vereinfachte Sequenz mit dem spätesten Datum bekommen. Jetzt möchte ich das Startdatum und Enddatum jeder Sequenz erhalten. Nehmen wir an, dass die Tabelle noch so:Wie vereinfacht man Sequenzdaten in MySQL?

ID DATE STATUS 
1  0106  A 
1  0107  A 
1  0112  A 
1  0130  B 
1  0201  A 
2  0102  C 
2  0107  C 

und ich möchte das Ergebnis wie folgt erhalten:

ID START_DATE END_DATE STATUS 
1  0106   0112  A 
1  0130   0130  B 
1  0201   0201  A 
2  0102   0107  C 

ich die Antwort des ehemaligen Frage es allerdings anzupassen versucht, scheiterte aber. Ich frage mich, wie ich es realisieren kann.

+0

ich aber über diese für ein bisschen nicht verwendet. Und ich weiß nicht, was in MySQL verfügbar ist (T/SQL hat jetzt Lead- und Lag-Funktionen, die möglicherweise anwendbar sind). Ich konnte mir keine einfache reine SQL-Lösung vorstellen (d. H. Nur Operationen festlegen). Der interative Ansatz ist jedoch geradlinig. Ordnen Sie diese Daten so an, wie Sie sie haben, und durchlaufen Sie sie, und erkennen Sie, wann immer sich die ID oder der Status über die vorherige Zeile ändert. Das hängt von einer Start- oder Endzeit ab oder davon, ob sich der Status oder die ID ändert. Fügen Sie für jeden Übergang eine Zeile in eine neue Tabelle ein. –

+0

können Sie einen Trick mit gespeicherten Prozedur verwenden. –

Antwort

0

Vor diesem

SELECT * FROM T; 
+------+------+--------+ 
| ID | DATE | STATUS | 
+------+------+--------+ 
| 1 | 106 | A  | 
| 1 | 107 | A  | 
| 1 | 112 | A  | 
| 1 | 130 | B  | 
| 1 | 201 | A  | 
| 2 | 102 | C  | 
| 2 | 107 | C  | 
+------+------+--------+ 

Es ist ziemlich einfach, einen Block und seqno mit diesen

SELECT T.ID,T.DATE,T.STATUS, 
      IF(STATUS <> @PREVS,@RN:[email protected]+1,@RN:[email protected]) RNBLOCK , 
      IF(STATUS = @PREVS,@RN2:[email protected]+1,@RN2:=1) RNSEQ , 
      @PREVS:=STATUS PSTATUS 
FROM  (SELECT @RN:=1) RNBLOCK, (SELECT @RN2:=0) RNSEQ,(SELECT @PREVS:=NULL) P, T 

zu geben, diesen

+------+------+--------+---------+-------+---------+ 
| ID | DATE | STATUS | RNBLOCK | RNSEQ | PSTATUS | 
+------+------+--------+---------+-------+---------+ 
| 1 | 106 | A  | 1  |  1 | A  | 
| 1 | 107 | A  | 1  |  2 | A  | 
| 1 | 112 | A  | 1  |  3 | A  | 
| 1 | 130 | B  | 2  |  1 | B  | 
| 1 | 201 | A  | 3  |  1 | A  | 
| 2 | 102 | C  | 4  |  1 | C  | 
| 2 | 107 | C  | 4  |  2 | C  | 
+------+------+--------+---------+-------+---------+ 

So, jetzt zu vergeben haben wir die Blöcke isoliert und wissen die min seq no (1) und die max seqno und wir können sie in eine Tabelle

schieben
drop table t1; 
CREATE TABLE `t1` (
    `ID` INT(11) NULL DEFAULT NULL, 
    `DATE` INT(11) NULL DEFAULT NULL, 
    `STATUS` VARCHAR(1) NULL DEFAULT NULL, 
    `rnblock` int null default null, 
    `rnseq` int null default null, 
    `pstatus` VARCHAR(1) NULL DEFAULT NULL 
) 
COLLATE='latin1_swedish_ci' 
ENGINE=InnoDB 
; 

und eine einfache min max beitreten

SELECT T2.ID,T2.DATE,T3.DATE,T2.STATUS FROM 
(  
SELECT T1.RNBLOCK,MAX(T1.RNSEQ) MAXSEQ 
FROM  T1 
GROUP  BY RNBLOCK 
) S 
JOIN  T1 T2 ON T2.RNBLOCK = S.RNBLOCK AND T2.RNSEQ = 1 
JOIN  T1 T3 ON T3.RNBLOCK = S.RNBLOCK AND T3.RNSEQ = S.MAXSEQ 

erstellen Diesen

+------+------+------+--------+ 
| ID | DATE | DATE | STATUS | 
+------+------+------+--------+ 
| 1 | 106 | 112 | A  | 
| 1 | 130 | 130 | B  | 
| 1 | 201 | 201 | A  | 
| 2 | 102 | 107 | C  | 
+------+------+------+--------+ 

Der Nachteil zu bekommen, ist, dass Sie eine Tabelle erstellen haben, damit es funktioniert.

Oder Sie könnten diese eher plump Code benutzen, die keine Zwischen Tabelle

select u.id,u.date,v.date,u.status from 
(
select s.rnblock,s.status,min(s.rnseq) minseq,max(s.rnseq) maxseq 
from 
(
SELECT T.ID,T.DATE,T.STATUS, 
      IF(STATUS <> @PREVS,@RN:[email protected]+1,@RN:[email protected]) RNBLOCK , 
      IF(STATUS = @PREVS,@RN2:[email protected]+1,@RN2:=1) RNSEQ , 
      @PREVS:=STATUS PSTATUS 
FROM  (SELECT @RN:=1) RNBLOCK, (SELECT @RN2:=0) RNSEQ,(SELECT @PREVS:=NULL) P, T 
) s 
group  by s.rnblock,s.status 
) T 
join 
(SELECT  T.ID,T.DATE,T.STATUS, 
      IF(STATUS <> @PREVS2,@RN3:[email protected]+1,@RN3:[email protected]) RNBLOCK , 
      IF(STATUS = @PREVS2,@RN4:[email protected]+1,@RN4:=1) RNSEQ , 
      @PREVS2:=STATUS PSTATUS 
FROM  (SELECT @RN3:=1) RNBLOCK, (SELECT @RN4:=0) RNSEQ,(SELECT @PREVS2:=NULL) P, T 
) u on u.rnblock = t.rnblock and u.rnseq = minseq 
join 
(SELECT  T.ID,T.DATE,T.STATUS, 
      IF(STATUS <> @PREVS3,@RN5:[email protected]+1,@RN5:[email protected]) RNBLOCK , 
      IF(STATUS = @PREVS3,@RN6:[email protected]+1,@RN6:=1) RNSEQ , 
      @PREVS3:=STATUS PSTATUS 
FROM  (SELECT @RN5:=1) RNBLOCK, (SELECT @RN6:=0) RNSEQ,(SELECT @PREVS3:=NULL) P, T 
) v on v.rnblock = t.rnblock and v.rnseq = maxseq 
0

Oh ich habe mir gerade eine Methode ausgedacht, obwohl es sehr dumm scheint. Die Methode führt nur den Code aus How to get temporal sequence by mysql zweimal (in anderer Reihenfolge) aus und verbindet diese beiden Tabellen.

+0

Es scheint, dass Join einige Probleme haben wird. – natsuapo

Verwandte Themen