【问题标题】:Get data, count and group by DATETIME where date gap greater than X按日期间隔大于 X 的 DATETIME 获取数据、计数和分组
【发布时间】: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

结果:

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

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

【问题讨论】:

    标签: sql mariadb


    【解决方案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 分钟。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-01
      相关资源
      最近更新 更多