之前我曾在How to get temporal sequence by 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 :(得分:0)
哦,我刚刚想出了一个方法虽然看起来很愚蠢。该方法只是执行How to get temporal sequence by mysql的代码两次(按不同顺序)并加入这两个表。
答案 1 :(得分: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 |
+------+------+--------+
使用此
分配块和seqno非常简单SELECT T.ID,T.DATE,T.STATUS,
IF(STATUS <> @PREVS,@RN:=@RN+1,@RN:=@RN) RNBLOCK ,
IF(STATUS = @PREVS,@RN2:=@RN2+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 |
+------+------+--------+---------+-------+---------+
所以现在我们已经隔离了块并且知道了最小序号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:=@RN+1,@RN:=@RN) RNBLOCK ,
IF(STATUS = @PREVS,@RN2:=@RN2+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:=@RN3+1,@RN3:=@RN3) RNBLOCK ,
IF(STATUS = @PREVS2,@RN4:=@RN4+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:=@RN5+1,@RN5:=@RN5) RNBLOCK ,
IF(STATUS = @PREVS3,@RN6:=@RN6+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