【问题标题】:Find longest consecutive series in mysql database在mysql数据库中查找最长的连续系列
【发布时间】:2018-07-31 14:31:15
【问题描述】:

我想在包含日志文件的数据库中查找最长的连续序列。 该文件具有以下结构:

select * from log;
+---------------+-------------------+---+
|sequence_number|timestamp          |...|
|---------------+-------------------+---+
|1              |2012-02-21 13:31:21|...|
|2              |2012-02-21 13:31:58|...|
|3              |2012-02-21 13:32:01|...|
|4              |2012-02-21 13:33:24|...|
|5              |2012-02-25 05:41:12|...|
|6              |2012-02-25 05:41:51|...|

etc...

我想查找具有最长连续条目系列的期间的开始日期和结束日期,其中两行之间的时间差小于一分钟。上面数据库的结果应该是:

+-------------------+-------------------+----+
|start_date         |end_date           |size|
+-------------------+-------------------+----+
|2012-02-21 13:31:21|2012-02-21 13:32:01|3   |
|2012-02-25 05:41:21|2012-02-25 05:41:51|2   |
|2012-02-21 13:33:24|2012-02-21 13:33:24|1   |

我检查了一些提示,但可以找到适合 mysql (MariaDB 10.1.23) 的解决方案

希望有人能帮忙,已经谢谢了!

【问题讨论】:

  • 忽略平局是什么意思?据我所见,执行后的解决方案可悲地没有任何意义......
  • 结果我不需要它们。但重要的是要获得连续序列的大小,即序列中没有中断的记录数。
  • 但是您的 @prevx := 时间戳始终等于时间戳,并且 i 和 j 值对我来说没有任何意义...有什么我看不到的吗?
  • 这很好用,你能把这个作为anwser发布吗?

标签: mysql sql timestamp


【解决方案1】:

这里有一个想法:

DROP TABLE IF EXISTS log;

CREATE TABLE  log
    (`sequence_number` int, `timestamp` timestamp)
;

INSERT INTO  log
    (`sequence_number`, `timestamp`)
VALUES
    (1, '2012-02-21 13:31:21'),
    (2, '2012-02-21 13:31:58'),
    (3, '2012-02-21 13:32:01'),
    (4, '2012-02-21 13:33:24'),
    (5, '2012-02-25 05:41:12'),
    (6, '2012-02-25 05:41:51')
;

 SELECT MIN(timestamp) start
      , MAX(timestamp) end
      , COUNT(*) total
   FROM 
      ( SELECT l.*
             , CASE WHEN @prevx > timestamp - INTERVAL 60 SECOND THEN @ix:=@ix+1 ELSE @ix:=1 END i
             , CASE WHEN @ix=1 THEN @jx:=@jx+1 ELSE @jx:=@jx END j
             , @prevx := timestamp
          FROM log l
             , (SELECT @prevx:=null,@ix:=1,@jx:=0) vars
         ORDER  
            BY l.timestamp
      ) x
  GROUP 
     BY j
  ;

给出以下输出:

+---------------------+---------------------+-------+
| start               | end                 | total |
+---------------------+---------------------+-------+
| 2012-02-21 13:31:21 | 2012-02-21.13:32:01 |     3 |
| 2012-02-21 13:33:24 | 2012-02-21.13:33:24 |     1 |
| 2012-02-25 05:41:12 | 2012-02-25.05:41:51 |     2 |
+---------------------+---------------------+-------+

http://sqlfiddle.com/#!9/777360/19

【讨论】:

    【解决方案2】:

    在 V8.0 之前的版本中,您可以使用变量:

    select min(timestamp), max(timestamp), count(*)
    from (select l.*,
                 (case when (@tmp_prevts := @prevts) = NULL then NULL
                       when (@prevts := timestamp) = NULL then NULL
                       when @tmp_prevts > timestamp - interval 1 minute then @grp
                       else (@grp := @grp + 1)
                  end) as grp
          from (select l.*
                from log l
                order by l.timestamp
               ) l cross join
               (select @prevts := '', @grp := 0) params
         ) l
    group by grp
    order by count(*) desc;
    

    【讨论】:

    • 但这不适用于 MariaDB 10.1.23。您能解释一下 V8.0 之前的版本是什么意思吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-04
    • 2021-06-23
    相关资源
    最近更新 更多