Skip to content
Advertisement

Count rows between time periods excluding time-overlap

I have a table where it holds some vehicle events, I need to count the number of event occurrences every 5 minutes.

Sample :

CREATE TABLE Sample (
  Id INT PRIMARY KEY NOT NULL, 
  EventTime DATETIME NOT NULL, 
  AssetId BIGINT NOT NULL, 
  EventTypeId BIGINT NOT NULL, 
  SeverityId INT NOT NULL
)
INSERT INTO Sample VALUES
    (1,'2022-04-03 14:00:35',1166146709699346432,7222537533950015177,1),
    (2,'2022-04-03 14:06:37',1166146709699346432,7222537533950015177,1),
    (3,'2022-04-03 14:08:50',1166146709699346432,7222537533950015177,1),
    (4,'2022-04-03 14:09:48',1166146709699346432,7222537533950015177,1),
    (5,'2022-04-03 14:22:35',1166146709699346432,7222537533950015177,1),
    (6,'2022-04-03 14:22:55',1166146709699346432,7222537533950015177,1),
    (7,'2022-04-03 14:23:21',1166146709699346432,7222537533950015177,1),
    (8,'2022-04-03 14:25:02',1166146709699346432,7222537533950015177,1),
    (9,'2022-04-03 14:26:36',1166146709699346432,7222537533950015177,1),
    (10,'2022-04-03 15:07:55',1166146709699346432,7222537533950015177,1),
    (11,'2022-04-03 15:13:13',1166146709699346432,7222537533950015177,1),
    (12,'2022-04-03 15:14:28',1166146709699346432,7222537533950015177,1),
    (13,'2022-04-03 17:15:15',1166146709699346432,7222537533950015177,1),
    (14,'2022-04-03 17:19:47',1166146709699346432,7222537533950015177,1),
    (15,'2022-04-03 17:21:57',1166146709699346432,7222537533950015177,1),
    (16,'2022-04-03 18:09:02',1166146709699346432,7222537533950015177,1),
    (17,'2022-04-03 18:23:07',1166146709699346432,7222537533950015177,1),
    (18,'2022-04-03 18:27:05',1166146709699346432,7222537533950015177,1),
    (19,'2022-04-03 18:45:24',1166146709699346432,7222537533950015177,1),
    (20,'2022-04-03 18:45:55',1166146709699346432,7222537533950015177,1),
    (21,'2022-04-03 19:09:40',1166146709699346432,7222537533950015177,1),
    (22,'2022-04-03 19:10:31',1166146709699346432,7222537533950015177,1),
    (23,'2022-04-03 19:25:03',1166146709699346432,7222537533950015177,1),
    (24,'2022-04-03 19:32:05',1166146709699346432,7222537533950015177,1),
    (25,'2022-04-03 19:44:47',1166146709699346432,7222537533950015177,1),
    (26,'2022-04-03 19:46:43',1166146709699346432,7222537533950015177,1),
    (27,'2022-04-03 19:49:44',1166146709699346432,7222537533950015177,1),
    (28,'2022-04-03 19:50:59',1166146709699346432,7222537533950015177,1),
    (29,'2022-04-03 19:54:10',1166146709699346432,7222537533950015177,1),
    (30,'2022-04-03 20:00:36',1166146709699346432,7222537533950015177,1),
    (31,'2022-04-03 20:02:37',1166146709699346432,7222537533950015177,1),
    (32,'2022-04-03 20:02:46',1166146709699346432,7222537533950015177,1),
    (33,'2022-04-03 20:02:54',1166146709699346432,7222537533950015177,1),
    (34,'2022-04-03 20:15:03',1166146709699346432,7222537533950015177,1),
    (35,'2022-04-03 20:17:01',1166146709699346432,7222537533950015177,1),
    (36,'2022-04-03 20:17:12',1166146709699346432,7222537533950015177,1)

I was able to get the results by the following query :

SELECT *
FROM (
SELECT 
   Id
 , EventTime
 , DATEADD(MINUTE, 5, e1.EventTime) EndOfPeriod
 , AssetId
 , EventTypeId
 , SeverityId 
, (
  SELECT COUNT(*) CNT
  FROM Sample e2
  WHERE 
  e2.EventTime >= e1.EventTime
  AND e2.EventTime <= DATEADD(MINUTE, 5, e1.EventTime)      
  AND e2.EventTypeId = e1.EventTypeId
  AND e2.AssetId = e1.AssetId
  AND e2.SeverityId = e1.SeverityId
) TotalEvents
,   CASE 
      WHEN e1.EventTime <= MAX(DATEADD(MINUTE, 5, e1.EventTime)) OVER(ORDER BY e1.EventTime, DATEADD(MINUTE, 5, e1.EventTime) ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) 
      THEN 0 ELSE 1 END AS IsIncluded
FROM Sample e1
) e 
WHERE IsIncluded = 1

query results :

| Id |            EventTime |          EndOfPeriod |             AssetId |         EventTypeId | SeverityId | TotalEvents | IsIncluded |
|----|----------------------|----------------------|---------------------|---------------------|------------|-------------|------------|
|  1 | 2022-04-03T14:00:35Z | 2022-04-03T14:05:35Z | 1166146709699346400 | 7222537533950015000 |          1 |           1 |          1 |
|  2 | 2022-04-03T14:06:37Z | 2022-04-03T14:11:37Z | 1166146709699346400 | 7222537533950015000 |          1 |           3 |          1 |
|  5 | 2022-04-03T14:22:35Z | 2022-04-03T14:27:35Z | 1166146709699346400 | 7222537533950015000 |          1 |           5 |          1 |
| 10 | 2022-04-03T15:07:55Z | 2022-04-03T15:12:55Z | 1166146709699346400 | 7222537533950015000 |          1 |           1 |          1 |
| 11 | 2022-04-03T15:13:13Z | 2022-04-03T15:18:13Z | 1166146709699346400 | 7222537533950015000 |          1 |           2 |          1 |
| 13 | 2022-04-03T17:15:15Z | 2022-04-03T17:20:15Z | 1166146709699346400 | 7222537533950015000 |          1 |           2 |          1 |
| 16 | 2022-04-03T18:09:02Z | 2022-04-03T18:14:02Z | 1166146709699346400 | 7222537533950015000 |          1 |           1 |          1 |
| 17 | 2022-04-03T18:23:07Z | 2022-04-03T18:28:07Z | 1166146709699346400 | 7222537533950015000 |          1 |           2 |          1 |
| 19 | 2022-04-03T18:45:24Z | 2022-04-03T18:50:24Z | 1166146709699346400 | 7222537533950015000 |          1 |           2 |          1 |
| 21 | 2022-04-03T19:09:40Z | 2022-04-03T19:14:40Z | 1166146709699346400 | 7222537533950015000 |          1 |           2 |          1 |
| 23 | 2022-04-03T19:25:03Z | 2022-04-03T19:30:03Z | 1166146709699346400 | 7222537533950015000 |          1 |           1 |          1 |
| 24 | 2022-04-03T19:32:05Z | 2022-04-03T19:37:05Z | 1166146709699346400 | 7222537533950015000 |          1 |           1 |          1 |
| 25 | 2022-04-03T19:44:47Z | 2022-04-03T19:49:47Z | 1166146709699346400 | 7222537533950015000 |          1 |           3 |          1 |
| 30 | 2022-04-03T20:00:36Z | 2022-04-03T20:05:36Z | 1166146709699346400 | 7222537533950015000 |          1 |           4 |          1 |
| 34 | 2022-04-03T20:15:03Z | 2022-04-03T20:20:03Z | 1166146709699346400 | 7222537533950015000 |          1 |           3 |          1 |

The issue with the above results is that the query excluded Ids (15 and 28) the correct output should be :

| Id |            EventTime |          EndOfPeriod |             AssetId |         EventTypeId | SeverityId | TotalEvents | IsIncluded |
|----|----------------------|----------------------|---------------------|---------------------|------------|-------------|------------|
|  1 | 2022-04-03T14:00:35Z | 2022-04-03T14:05:35Z | 1166146709699346400 | 7222537533950015000 |          1 |           1 |          1 |
|  2 | 2022-04-03T14:06:37Z | 2022-04-03T14:11:37Z | 1166146709699346400 | 7222537533950015000 |          1 |           3 |          1 |
|  5 | 2022-04-03T14:22:35Z | 2022-04-03T14:27:35Z | 1166146709699346400 | 7222537533950015000 |          1 |           5 |          1 |
| 10 | 2022-04-03T15:07:55Z | 2022-04-03T15:12:55Z | 1166146709699346400 | 7222537533950015000 |          1 |           1 |          1 |
| 11 | 2022-04-03T15:13:13Z | 2022-04-03T15:18:13Z | 1166146709699346400 | 7222537533950015000 |          1 |           2 |          1 |
| 13 | 2022-04-03T17:15:15Z | 2022-04-03T17:20:15Z | 1166146709699346400 | 7222537533950015000 |          1 |           2 |          1 |
| 15 | 2022-04-03T17:21:57Z | 2022-04-03T17:26:57Z | 1166146709699346400 | 7222537533950015000 |          1 |           1 |          1 |
| 16 | 2022-04-03T18:09:02Z | 2022-04-03T18:14:02Z | 1166146709699346400 | 7222537533950015000 |          1 |           1 |          1 |
| 17 | 2022-04-03T18:23:07Z | 2022-04-03T18:28:07Z | 1166146709699346400 | 7222537533950015000 |          1 |           2 |          1 |
| 19 | 2022-04-03T18:45:24Z | 2022-04-03T18:50:24Z | 1166146709699346400 | 7222537533950015000 |          1 |           2 |          1 |
| 21 | 2022-04-03T19:09:40Z | 2022-04-03T19:14:40Z | 1166146709699346400 | 7222537533950015000 |          1 |           2 |          1 |
| 23 | 2022-04-03T19:25:03Z | 2022-04-03T19:30:03Z | 1166146709699346400 | 7222537533950015000 |          1 |           1 |          1 |
| 24 | 2022-04-03T19:32:05Z | 2022-04-03T19:37:05Z | 1166146709699346400 | 7222537533950015000 |          1 |           1 |          1 |
| 25 | 2022-04-03T19:44:47Z | 2022-04-03T19:49:47Z | 1166146709699346400 | 7222537533950015000 |          1 |           3 |          1 |
| 28 | 2022-04-03T19:50:59Z | 2022-04-03T19:55:59Z | 1166146709699346400 | 7222537533950015000 |          1 |           2 |          1 |
| 30 | 2022-04-03T20:00:36Z | 2022-04-03T20:05:36Z | 1166146709699346400 | 7222537533950015000 |          1 |           4 |          1 |
| 34 | 2022-04-03T20:15:03Z | 2022-04-03T20:20:03Z | 1166146709699346400 | 7222537533950015000 |          1 |           3 |          1 |

SQLFiddle

your help would be much appreciated.

Advertisement

Answer

I believe this can only be done via recursive cte because the 5 minute window can contain arbitrary number of rows… a situation where lead/lag/rows between x preceding will not work. Here is my stab at it:

with ncte as (
    select *, rn = row_number() over (partition by AssetId, EventTypeId, SeverityId order by EventTime)
    from sample
), rcte as (
    select Id, EventTime, AssetId, EventTypeId, SeverityId, rn, EventTime as BaseTime
    from ncte
    where rn = 1

    union all

    select curr.Id, curr.EventTime, curr.AssetId, curr.EventTypeId, curr.SeverityId, curr.rn, case
        when curr.EventTime < dateadd(minute, 5, prev.BaseTime) then prev.BaseTime
        else curr.EventTime
    end
    from ncte as curr
    join rcte as prev on
        curr.rn = prev.rn + 1 and
        curr.AssetId = prev.AssetId and
        curr.EventTypeId = prev.EventTypeId and
        curr.SeverityId = prev.SeverityId
)
select min(case when EventTime = BaseTime then Id end), AssetId, EventTypeId, SeverityId, BaseTime, count(*) as TotalEvents 
from rcte
group by AssetId, EventTypeId, SeverityId, BaseTime

Demo on db<>fiddle

User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement