获取日期间隔大于X的DATETIME的数据,计数和分组

时间:2018-08-13 14:29:46

标签: sql mariadb

我有很多会话同时运行一个特定的API。该API会不时更新,导致所有会话都消失。

发生这种情况时,每个会话都会向我的中央网站报告一个错误“ 830”。

数据最终看起来像这样:

uid------error-------date
41       830         2018-05-14 13:45:13
42       830         2018-05-14 13:45:14
43       830         2018-05-14 13:45:16
44       830         2018-05-14 13:45:23
46       830         2018-05-14 13:46:19
50       830         2018-05-15 04:12:49
80       830         2018-05-15 04:12:49
36       830         2018-05-15 04:12:50
91       830         2018-05-15 04:15:52
12       830         2018-05-15 07:45:11
88       830         2018-05-15 07:45:11
92       830         2018-05-15 07:45:12

由于它随时可能发生,因此我需要能够根据下一个数据位之间的间隔对这些数据进行分组。

例如,这是我想与上面的数据一起获得的输出,并按原样输出(间隙> 10分钟):

update_date-----update_count
2018-05-14      1
2018-05-15      2

这是到目前为止我已经尝试过的方法:

select
    count(eresult) as error_count,
    CAST(added AS DATE) as error_date
from st__errors
where 1=1
and eresult = 20
group by date(added)
order by id desc

结果:

enter image description here

这将对所有数据进行分组和计数,但是并不能解决差距,并且不会按我停留的日期差距进行分组。

我需要每天根据每个错误日期之间的间隔对数据进行分组。我的解释很不好,但是希望这些例子能更好地说明我要达到的目标?

3 个答案:

答案 0 :(得分:1)

这将是一个非常慢的查询,但这是一个选择:

select    count(e.eresult) as error_count,
          CAST(e.added AS DATE) as error_date
from      st__errors as e
where (
       SELECT  TIME_TO_SEC(TIMEDIFF(e.added, ei.added)) 
       FROM    st__errors as ei WHERE ei.id = e.id - 1
      ) > 10
      and e.eresult = 20
group by date(e.added)
order by e.id desc

答案 1 :(得分:0)

虽然不漂亮,但是我认为可以通过JOIN来完成:

   SELECT COUNT(*) grouped_error_count,
          DATE(e1.added) error_date
     FROM st__errors e1

/* Find other error within 10 mins */
LEFT JOIN st__errors e2
       ON e2.added < e1.added 
      AND e2.added >= e1.added - INTERVAL 10 MINUTE 

/* Find other error with exact same time (but only count one) */
LEFT JOIN st__errors e3
       ON e3.added = e1.added 
      AND e3.id < e1.id 

/* Has neither of the above */
    WHERE e2.id IS NULL
      AND e3.id IS NULL 

 GROUP BY error_date
 ORDER BY error_date DESC;   

我不使用id = id - 1(或使用ID进行订购),因为它依赖于ID是连续的,即使完成了auto_increment,当手动插入完成或某些插入失败时,id也是容易出错的。

我的查询仍应允许在添加的列上使用索引。

此外,如果这将是一项功能,而不仅仅是一个一次性查询,那么我将考虑将您的分组添加到录音中。这将使您的查询更快,更易读。

答案 2 :(得分:0)

这是一种更快的方法,但有时会将一组视为两个。

SELECT FLOOR(UNIX_TIMESTAMP(datetime) / (10*60)) AS ten_min_bucket,
       COUNT(*) AS err_ct
    FROM st__errors
    GROUP BY ten_min_bucket;

一个变体可以让您查看时间范围:

SELECT MIN(datetime) AS err_start,
       MAX(datetime) AS err_end,
       COUNT(*) AS err_ct
    FROM st__errors
    GROUP BY FLOOR(UNIX_TIMESTAMP(datetime) / (10*60));

如果在前一个结束后几秒钟内看到一个错误簇,您将知道它们属于同一类。习惯了“缺陷”之后,您可能希望将分辨率降低到5分钟。