2016-07-23 23 views
0

我之前在How to get temporal sequence by mysql上提出了一個問題。在那裏我想要獲得最新日期的簡化序列。 現在我想獲得每個序列的開始日期和結束日期。假設表仍然是這樣的:如何簡化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 

,我想要得到的結果是這樣的:

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

我想雖然對前一個問題的答案適應它,但失敗了。我想知道如何才能實現它。

+0

不過,我覺得這個對位。因爲我不知道MySQL中有什麼可用的聲明和哨聲(T/SQL現在具有可能適用的前導和滯後函數)。我想不出一個直接的純粹的SQL解決方案(即只有集合操作)。然而,交互方法是直截了當的。按照您擁有的方式對數據進行排序,然後遍歷它,並檢測以前的行ID或狀態是否更改。這是開始或結束時間取決於狀態或ID是否正在改變。在每個轉換的新表格中插入一行。 –

+0

你可以使用一些使用存儲過程的技巧。 –

回答

0

鑑於這種

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

這是很簡單的使用這個

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 

爲了給這個

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

所以,現在我們已經分離塊,知道分配塊的SeqNo min seq no(1)和max seqno,我們可以將它們推入表格

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 
; 

,並創建一個簡單的最小值最大值加入

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 

得到這個

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

的缺點是,你必須創建一個表,使其工作。

或者你可以使用這個相當笨拙的代碼不使用中間表

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 
相關問題