如何使用 SQL 测试 5 分钟间隔,给定 AWS Athena 中的 Windows 事件管理器事件时间戳

How to test for 5 minute intervals with SQL, given Windows Event Manager event timestamps in AWS Athena

我在 AWS 中使用 Athena 和 Windows 事件管理器日志来构造一些安全事件查询。其中之一是我想查询在 5 分钟内报告 3 次或更多失败登录尝试的机器。

时间戳列的格式如下:2019-03-25T19:18:10.7954381Z

我已经找到了具有该特定事件 ID 的机器:SELECT machinename, COUNT(eventid) FROM windows WHERE eventid = 4625 GROUP BY machinename HAVING COUNT(eventid = 4625) >= 3;

对于任何时间戳,它只是 returns 所有 eventid 大于或等于 3 的机器。

我的问题是:我将如何在 SQL 中实现逻辑来检查特定事件 ID 是否在 5 分钟的时间跨度内发生并带有那种时间戳,而不是只显示所有时间?

这是我第一次涉足SQL;任何帮助是极大的赞赏。谢谢!

编辑: 西奥有解决办法。发帖于此:

SELECT FROM_UNIXTIME( FLOOR( TO_UNIXTIME( DATE_PARSE(substr(timecreated, 1, 16), '%Y-%m-%dT%H:%i') )/300 ) * 300 ) AS five_minute_window, machine-name, COUNT(event-id) AS event_count FROM table WHERE event-id = 4625 GROUP BY 1, machine-name HAVING COUNT(event-id = 4625) >= 3;

我不得不去掉小数秒,因为有一些异常的时间戳不是这样格式化的(只有整秒)。

所以你想在 n 分钟四舍五入,对吗?我将 oracle 语法放在下面,但请注意所有数据库都具有相似的功能。方法是"round"或"truncate"那一分钟的数据。所以它是 10:43 - return 10:40。一旦你得到它,你就可以按那个分组

  • oracle 中的 sysdate return 当前 date/time - 用于测试
  • to_char 转换给定格式的日期或数字
  • trunc(或round)用于截断数值运算
  • to_date是把一个格式的字符串转成日期
select actual_date,
       to_date(to_char(actual_date,'YYYYMMDDHH24') || min_trunc_5,'YYYYMMDDHH24MI') rouded_to_5_dt,
       min_trunc_5
from
(
    select sysdate  actual_date, 
           ltrim(to_char(trunc(to_number(to_char(sysdate,'MI')/5))*5,'09')) min_trunc_5
    from dual
) x

它return适合我

actual_date      rounded_to_5_dt min_trunc_5
20190410084837   20190410084500  45

看看 48 是如何变成 45 的。现在,如果在任何日期进行这种类型的操作并以此为依据,我将对 5 分钟范围内的所有数据进行分组

在 Athena 中,您可以使用 DATE_TRUNC 函数将时间戳截断为整分钟、整小时等。不幸的是,它不支持单位的倍数,因此五分钟是不可能的。

我通常这样做:FROM_UNIXTIME(FLOOR(TO_UNIXTIME("timestamp")/300) * 300)。它的作用是转换为 UNIX 时间戳,即自 1970 年以来的秒数,除以 300 以获得自 1970 年以来的五分钟间隔数,将其四舍五入为整数,然后再次乘以 300 以转换回秒数, 然后转换回时间戳。这适用于任何时间间隔,只需将 300 更改为 1800 以四舍五入为半小时等。

Athena 本身不支持您的时间戳格式,因此您需要对其进行解析,这是通过 DATE_PARSE 完成的——例如 DATE_PARSE("timestamp_column", '%Y-%m-%dT%H:%M:%S.%fZ').

完整示例可能如下所示:

SELECT
  FROM_UNIXTIME(
    FLOOR(
      TO_UNIXTIME(
        DATE_PARSE("timestamp_column", '%Y-%m-%dT%H:%M:%S.%fZ')
      )/300
    ) * 300
  ) AS five_minute_window,
  COUNT(*) AS event_count
FROM some_table
GROUP BY 1

这将为您提供每五分钟的行数 window。您可以添加 WHERE 以过滤特定行,并添加外部查询以查找包含许多事件的 windows 等