Bri*_*ach 5 mysql gaps-and-islands
我有一个具有以下结构的数据库
+---------------------+------------+---------------+
| timestamp | EngOilP_sd | CompOilLVL_sd |
+---------------------+------------+---------------+
| 2015-06-24 20:28:07 | 0 | 0 |
| 2015-06-24 20:30:20 | 1 | 0 |
| 2015-06-24 20:36:47 | 1 | 0 |
| 2015-06-24 20:41:11 | 1 | 0 |
| 2015-06-24 20:43:29 | 1 | 0 |
| 2015-06-24 20:45:42 | 0 | 0 |
| 2015-06-24 20:47:51 | 0 | 0 |
| 2015-06-24 20:49:59 | 0 | 1 |
| 2015-06-24 20:52:01 | 0 | 1 |
| 2015-06-24 20:54:17 | 0 | 0 |
+---------------------+------------+---------------+
Run Code Online (Sandbox Code Playgroud)
我想生成如下报告:
sd duration start stop
EngOilP_sd 15min 22s 2015-06-24 20:30:20 2015-06-24 20:45:42
CompOilLVL_sd 4min 18s 2015-06-24 20:49:59 2015-06-24 20:54:17
Run Code Online (Sandbox Code Playgroud)
我应该补充一点,停止记录是第一个值 = 0 的记录并不重要,它可能是值 = 1 的最后一个记录
我如何轻松地创建一个性能良好的查询来为我提供所需的信息?我正在为应用程序使用 Python,因此我不需要 SQL 以这种确切的形式输出报告,只需让我了解信息的内在即可。
可能有比这更优雅的东西,但由于您正在做一种枢轴(从列转换为行,即元数据到数据),它永远不会很漂亮。假设有一个表:
create table t
( ts timestamp not null
, EngOilP_sd smallint not null
, CompOilLVL_sd smallint not null
) engine = innodb;
insert into t (ts, EngOilP_sd, CompOilLVL_sd)
values
('2015-06-24 20:28:07',0 ,0 )
,('2015-06-24 20:30:20',1 ,0 )
,('2015-06-24 20:36:47',1 ,0 )
,('2015-06-24 20:41:11',1 ,0 )
,('2015-06-24 20:43:29',1 ,0 )
,('2015-06-24 20:45:42',0 ,0 )
,('2015-06-24 20:47:51',0 ,0 )
,('2015-06-24 20:49:59',0 ,1 )
,('2015-06-24 20:52:01',0 ,1 )
,('2015-06-24 20:54:17',0 ,0 );
Run Code Online (Sandbox Code Playgroud)
由于我们将多次引用“枢轴”,因此我们为其创建一个视图:
create view t_pivot as
select 'EngOilP_sd' as sd, ts, EngOilP_sd as val from t
union all
select 'CompOilLVL_sd', ts, CompOilLVL_sd from t;
Run Code Online (Sandbox Code Playgroud)
开始时间(使用@Pauls注释作为定义)是每个属性最早为1的时间:
select sd, min(case val when 1 then ts end) as start
from t_pivot
group by sd
Run Code Online (Sandbox Code Playgroud)
停止时间是各属性为0之后的最早时间:
select x.sd, x.start, min(case y.val when 0 then y.ts end) as stop
from (
select sd, min(case val when 1 then ts end) as start
from t_pivot
group by sd
) as x
join t_pivot as y
on x.sd = y.sd
and y.ts > x.start
group by x.sd, x.start
Run Code Online (Sandbox Code Playgroud)
添加另一层嵌套可以方便地确定持续时间:
select sd, timediff(stop, start) as duration, start, stop
from (
select x.sd, x.start, min(case y.val when 0 then y.ts end) as stop
from (
select sd, min(case val when 1 then ts end) as start
from t_pivot
group by sd
) as x
join t_pivot as y
on x.sd = y.sd
and y.ts > x.start
group by x.sd, x.start
) as z
order by sd desc;
+---------------+----------+---------------------+---------------------+
| sd | duration | start | stop |
+---------------+----------+---------------------+---------------------+
| EngOilP_sd | 00:15:22 | 2015-06-24 20:30:20 | 2015-06-24 20:45:42 |
| CompOilLVL_sd | 00:04:18 | 2015-06-24 20:49:59 | 2015-06-24 20:54:17 |
+---------------+----------+---------------------+---------------------+
2 rows in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
740 次 |
| 最近记录: |