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

Posted

技术标签:

【中文标题】按日期间隔大于 X 的 DATETIME 获取数据、计数和分组【英文标题】:Get data, count and group by DATETIME where date gap greater than X 【发布时间】:2018-08-13 14:29:46 【问题描述】:

我有很多针对某个特定 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

结果:

这对所有数据进行分组和计数,但不考虑间隔和按日期间隔分组,这是我遇到的问题。

我需要每天按每个错误日期之间的间隔对数据进行分组。我对自己的解释很糟糕,但希望这些例子能更好地描述我想要实现的目标?

【问题讨论】:

【参考方案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

【讨论】:

谢谢你——我真的很努力解决这个问题,但是通过你的回答,我需要做的事情变得更加明显并且它有效!欣赏它:) 虽然这可能有效,但不建议依赖 id 是连续的或以正确的顺序。【参考方案2】:

它并不漂亮,但我认为这可以通过 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,在手动插入完成或某些插入失败时也会出错。

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

另外,如果这将成为一项功能而不仅仅是一次性查询,我会考虑将您的分组构建到录音中。这将使您的查询更快、更易读。

【讨论】:

我在这个表中有很多数据,它似乎需要很长时间才能运行 - 现在超过 5 分钟,我已经重新启动了我的数据库一次 你有added的索引吗? 我会尽快回复您,我正在创建一个维护页面,这样我就可以在不杀死站点的情况下添加索引 x) 感谢您的帮助【参考方案3】:

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

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 分钟。

【讨论】:

以上是关于按日期间隔大于 X 的 DATETIME 获取数据、计数和分组的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 雄辩,其中日期等于或大于 DateTime

python 计算两个日期相差多少个月

使用单个查询获取每个多个日期间隔的条目数

SQL记录-PLSQL日期与时间

C# 计算两个日期的时间间隔

C# 计算两个日期的时间间隔