SQL:从第一次出现到接下来的五分钟计算某个值的出现次数,并在下一次出现时重复相同的次数

SQL: Counting occurrence of certain value from its first appearance till next five minutes and repeat the same for the next occurence again

我需要找出一个值 34 从第一次出现到接下来的 5 分钟出现的次数。

然后在 5 分钟后再次执行相同的操作,再次获取值为 20 的记录,查看每个设备在接下来的 5 分钟内发生了多少次

假设我有以下 table:

DevID      value             DateTime
--------------------------------------------------
99       20               18-12-2016 18:10
99       34               18-12-2016 18:11
99       34               18-12-2016 18:12
99       20               18-12-2016 18:15
23       15               18-12-2016 18:16
28       34               18-12-2016 18:17
23       15               18-12-2016 18:18
23       12               18-12-2016 18:19
99       20               18-12-2016 18:20
99       34               18-12-2016 18:21
99       34               18-12-2016 18:22
99       34               18-12-2016 18:23
99       34               18-12-2016 18:24
99       34               18-12-2016 18:25

我对数字 34 很感兴趣。我想检查数字 34 的第一次出现,获取它的时间,然后计算这个数字 (34) 在接下来的 5 分钟内出现了多少次。基本上从第一次出现到出现 +5 分钟获取记录,并计算其中有多少有 34 个,如果超过 3 个,则列出该设备名称。

在下一个 5 分钟之前对下一个记录重复相同的 34。所以在上面的例子中,记录 99 将在 2016 年 12 月 18 日首次获得 34 18:11 但随后我们在接下来的 5 分钟内没有获得超过 3 个 34 的记录但是我们在 18-12 再次获得 34 -2016 18:21 并在接下来的 5 分钟内获得了 3 个以上的 34 个条目

因此上述 table 的预期输出将是设备 ID 99。

已编辑

我只想找到值 34。因此不需要在 5 分钟间隔内找到所有此类重复值的额外复杂性。 只是想知道在 5 分钟的时间间隔之间我们有 34 个重复了 3 次以上的设备(这应该是可以更改的,我也可以将其硬编码为 10 次)。

请调整您的 RDBMS,但它应该看起来像这样:

select b.*
from (
    select value, min(DateTime) as md
    from the_table
    group by value
) as a
join the_table as b
on a.value = b.value
and b.DateTime between a.md and a.md + interval'5'minute

这可以按如下方式完成:

SELECT DevID
FROM t
WHERE Value = 34
AND 2 <= (
  SELECT COUNT(*)
  FROM t AS x
  WHERE x.DevID = t.DevID
  AND x.Value = t.Value
  AND x.DateTime > t.DateTime
  AND x.DateTime < DATEADD(MINUTE, 5, t.DateTime)
)
GROUP BY DevID

根据您计算 5 分钟的方式,您可能希望将 < 替换为 <=

最有效的方法是使用lag()/lead():

select t.*
from (select t.*,
             lead(datetime, 2) over (partition by devid order by datetime) as next2_dt
      from t
      where value = 34
     ) t
where next2_dt <= dateadd(minute, 5, datetime);

这会在第二个值之前达到峰值,并将该值的 datetime 与当前行的 datetime 进行比较。