MySQL获取间隙之间的持续时间

时间:2018-01-26 14:45:56

标签: mysql

我正在尝试计算单位不是100%的持续时间。

|ID| DATE               | UNITNAME | PERCENTAGE|  
------------------------------------------------
|1 |2018-01-20 00:00:00 | UNIT1    |100        |
|2 |2018-01-20 00:05:00 | UNIT1    |0          |
|3 |2018-01-20 00:10:00 | UNIT1    |100        |
|4 |2018-01-20 00:15:00 | UNIT1    |99         | 
|5 |2018-01-20 00:20:00 | UNIT1    |50         |
|6 |2018-01-20 00:25:00 | UNIT1    |100        |

所以在这里,我希望输出类似于:

| UNITNAME | RPO         |
| UNIT1    | 00:15:00    | 

单位在00:05:00报告为0%,然后在00:10:00报告的下一个间隔为100%。因此,我将假设该装置已经退出RPO 5分钟。这种情况会在00:15:00再次发生,直到00:25:00,因此假设整个期间都出现了这种情况。

我看起来很沮丧,并且在SQL Fiddle创建了关注 使用以下内容;

select UNITNAME, SEC_TO_TIME(SUM(TIME_TO_SEC(duration))) as 'RPO'
from(
      SELECT UNITNAME, TIMEDIFF(MAX(DATE), MIN(DATE)) AS duration, MIN(DATE) AS 
startime, MAX(DATE) AS endtime
FROM (
    SELECT 
tp.*
, @val_change := IF(@prev_val != Percentage, @val_change+1 , @val_change) AS vc
, @prev_val := Percentage
FROM
Replication_History tp 
, (SELECT @prev_val := NULL, @val_change := 0) var_init_subquery
ORDER BY UNITNAME, DATE
 ) sq
 WHERE Percentage =100 
 GROUP BY UNITNAME, vc
 )ts
 group by UNITNAME

这种作品,但没有正确管理100%之间的差距。

任何人做过类似的事情吗?

2 个答案:

答案 0 :(得分:2)

它只是这些值之间差异的总和......

SELECT a.unitname
     , MIN(a.date) my_start
     , a.min_date my_end 
  FROM 
     ( SELECT x.*
            , MIN(y.date) min_date 
         FROM replication_history x 
         LEFT 
         JOIN replication_history y 
           ON y.unitname = x.unitname 
          AND y.date > x.date 
          AND y.percentage = 100 
        WHERE x.percentage < 100 
        GROUP 
           BY x.id
     ) a 
 GROUP 
    BY unitname
     , my_end;
+----------+---------------------+---------------------+
| unitname | my_start            | my_end              |
+----------+---------------------+---------------------+
| UNIT1    | 2018-01-20 10:15:00 | 2018-01-20 10:25:00 |
| UNIT2    | 2018-01-20 10:05:00 | 2018-01-20 10:10:00 |
| UNIT2    | 2018-01-20 10:15:00 | 2018-01-20 10:25:00 |
+----------+---------------------+---------------------+

答案 1 :(得分:1)

你可以使用&#39; Gaps-and-islands&#39;来解决这个问题。的方法:

SELECT UNITNAME,  SEC_TO_TIME(SUM(TIME_TO_SEC(duration))) AS PRO
FROM (
   SELECT UNITNAME, TIMEDIFF(MAX(DATE), MIN(DATE)) AS duration
   FROM (
      SELECT ID, DATE, UNITNAME, Percentage,
             @rn := IF(@unit = UNITNAME, IF(Percentage = 100, @rn + 1, @rn),
                       IF(@unit := UNITNAME, 1, 1)) AS grp
      FROM replication_history
      CROSS JOIN (SELECT @unit := '', @rn := 0) AS v
      ORDER BY UNITNAME, DATE DESC) AS t
   GROUP BY UNITNAME, grp
   HAVING COUNT(CASE WHEN Percentage <> 100 THEN 1 END) > 0) AS u
GROUP BY UNITNAME 

要了解此查询的工作原理,您必须执行最里面的子查询并检查它产生的结果。

所以,这个查询:

SELECT ID, DATE, UNITNAME, Percentage, grp
FROM (
    SELECT ID, DATE, UNITNAME, Percentage,
         @rn := IF(@unit = UNITNAME, IF(Percentage = 100, @rn + 1, @rn),
                   IF(@unit := UNITNAME, 1, 1)) AS grp
    FROM replication_history
    CROSS JOIN (SELECT @unit := '', @rn := 0) AS v
    ORDER BY UNITNAME, DATE DESC) AS t
ORDER BY UNITNAME, DATE 

产生以下输出:

 ID,    DATE,                UNITNAME, Percentage, grp
-------------------------------------------------------
204200, 2018-01-20 10:00:00, UNIT1,    100,        3
204201, 2018-01-20 10:05:00, UNIT1,    0,          2
204202, 2018-01-20 10:10:00, UNIT1,    100,        2
204203, 2018-01-20 10:15:00, UNIT1,    99,         1
204204, 2018-01-20 10:20:00, UNIT1,    50,         1
204205, 2018-01-20 10:25:00, UNIT1,    100,        1

因此,正如您可以看到的上述数据,grp字段标识了PRO&#39;间隔。仅具有100百分比值的组将被第二级子查询过滤掉。

Demo here