3

我有一个这样的 MySQL 表:

CREATE TABLE IF NOT EXISTS `mytable` (
  `ts` datetime NOT NULL,
  `cnt` int(10) unsigned NOT NULL,
  PRIMARY KEY (`ts`)
) ENGINE=InnoDB;

每当我们获得更新时,我们都会在其中存储事件计数器的值;这些更新在任意时间到达。

如何提取每 X 时间(例如 5 分钟、一天、一个月等)的事件数?我可以将其简化为通过日期/时间 sql 函数(例如小时、天、月等)轻松提取的间隔。

虽然我们没有任何保证,但与我想提取的间隔相比,平均数据是“密集的”。例如。数据通常每小时多次出现,但我永远不会要求间隔小于 1 小时的事件计数。如果存储的数据中存在“问题”(例如大漏洞),则结果中存在“问题”是可以接受的。

例如,我可以通过这样的查询(24 小时示例)获得我感兴趣的计数器值:

SELECT ts, cnt
FROM mytable
GROUP BY DATE( ts ) 
ORDER BY ts DESC

...并且事件计数可以通过将每一行的计数器与其前任相减来轻松计算。但如果可能的话,我想在 SQL 中做到这一点。

另外,如果这个问题有一个好名字(我认为当你使用时间序列和计数器时这是一个相当常见的名字)我想知道它以提高我的词汇量:)

4

1 回答 1

3

如果您将 AUTO_INCREMENT PRIMARY KEY 添加到您的表中,那将是 aolveable。

您提供的表模式无效(PRIMARY KEY on timestamp,但没有这样的列)。

您是否介意我们:

ALTER TABLE mytable DROP PRIMARY KEY, ADD COLUMN id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY

?

如果是这样,那么可以完成以下操作,我将分步介绍:

SELECT
  TIMESTAMPDIFF(SECOND, m1.ts, m2.ts) AS diff_seconds,
  m2.cnt - m1.cnt AS diff_cnt
FROM
  mytable m1 JOIN mytable m2 ON (m1.id = m2.id-1)
;

以上显示了连续样本之间的时间和cnt差异。让我们添加第三列:

SELECT
  TIMESTAMPDIFF(SECOND, m1.ts, m2.ts) AS diff_seconds,
  m2.cnt - m1.cnt AS diff_cnt,
  (m2.cnt - m1.cnt)/TIMESTAMPDIFF(SECOND, m1.ts, m2.ts) AS cnt_per_second
FROM
  mytable m1 JOIN mytable m2 ON (m1.id = m2.id-1)
;

I evaluated cnt_per_second. Multiply by 60 to get cnt per minute, and so on.

Now, the total average would be:

SELECT 
  avg(cnt_per_second)
FROM (
  SELECT
    TIMESTAMPDIFF(SECOND, m1.ts, m2.ts) AS diff_seconds,
    m2.cnt - m1.cnt AS diff_cnt,
    (m2.cnt - m1.cnt)/TIMESTAMPDIFF(SECOND, m1.ts, m2.ts) AS cnt_per_second
  FROM
    mytable m1 JOIN mytable m2 ON (m1.id = m2.id-1)
) sel_diff
;

Add original n1.ts to first query if you want to know when a diff was recorded, and so you will also be able to know the average count events in a given time period.

于 2012-07-07T04:29:19.030 回答