3

A logger system saves every 5 seconds a row of data (seconds==0,5,10,15,...,55; a time like 23:00:07 is not possible).

Sometimes the logger doesn't save because of a communication error, and rows are simply missing from the table.

I need to detect these gaps: I want to read the last line before the gap and the first line after the gap.

These are the demo data:

create table #time (
    DateTime datetime not null,
    Value int not null
);

insert into #time (DateTime, Value)
    values
        ('2018-08-23 00:00:00', 123),
        ('2018-08-23 00:00:05', 152),
        ('2018-08-23 00:00:10',  37),
        ('2018-08-23 00:00:15', 141),
        ('2018-08-23 00:00:20',  41),
        ('2018-08-23 00:00:25',  35),
        ('2018-08-23 00:00:30', 143),
        ('2018-08-23 00:00:35',  67),
        ('2018-08-23 00:00:40', 111),
                                        /* gap of one minute here */
        ('2018-08-23 00:01:45', 123),
        ('2018-08-23 00:01:50', 145),
        ('2018-08-23 00:01:55', 141),
        ('2018-08-23 00:02:00',  87),
                                        /* gap of 10 seconds here */
        ('2018-08-23 00:02:15', 190),
        ('2018-08-23 00:02:20', 122),
        ('2018-08-23 00:02:25', 123);

select * from #time;

They are also at RexTester

I would like to read back:

    GapStart              GapEnd                Size
0   2018-08-23 00:00:40   2018-08-23 00:01:45   0000-00-00 00:01:45
1   2018-08-23 00:02:00   2018-08-23 00:02:15   0000-00-00 00:00:15

Of course gaps of 5 seconds shouldn't be listed

What I found is referred to start/end DateTimes in the same row (Find gaps in timesheet data between certain hours), or is too complicated for me to be adapted to my case (find gaps in sequential dates).

I'm using MariaDB 10.0.28 (it is not possible to upgrade it): it means LAG() is not available.

Thank you in advance

Tim Biegeleisen
  • 502,043
  • 27
  • 286
  • 360
Alex Poca
  • 2,406
  • 4
  • 25
  • 47

1 Answers1

3

One approach might be to first subquery and pair each record with the record having the nearest greater timestamp. Then, query that, and return all records having a gap of a sufficient size.

SELECT
    DateTime AS GapStart,
    NextDateTime AS GapEnd,
    TIMESTAMPDIFF(SECOND, DateTime, NextDateTime) AS SizeInSecond
FROM
(
    SELECT DateTime, Value,
        (SELECT MIN(DateTime) FROM #time t2
         WHERE t2.DateTime > t1.DateTime) AS NextDateTime
    FROM #time t1
) t
WHERE
    TIMESTAMPDIFF(SECOND, DateTime, NextDateTime) > 5;   -- or whatever threshhold you want

enter image description here

Demo

ADD ON to original answer

If DateTime is always growing, speed improvement can be obtained by changing the internal SELECT:

SELECT
    DateTime AS GapStart,
    NextDateTime AS GapEnd,
    TIMESTAMPDIFF(SECOND, DateTime, NextDateTime) AS SizeInSecond
FROM
(
    SELECT DateTime, Value,
        (SELECT DateTime FROM #time t2
         WHERE t2.DateTime > t1.DateTime LIMIT 1) AS NextDateTime
    FROM #time t1
) t
WHERE
    TIMESTAMPDIFF(SECOND, DateTime, NextDateTime) > 5;
Alex Poca
  • 2,406
  • 4
  • 25
  • 47
Tim Biegeleisen
  • 502,043
  • 27
  • 286
  • 360