计算时间段之间的行数,不包括时间重叠
Count rows between time periods excluding time-overlap
我有一个 table 用于保存一些车辆事件,我需要每 5 分钟计算一次事件发生的次数。
样本:
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)
我能够通过以下查询获得结果:
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
查询结果:
| 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 |
上述结果的问题是查询排除了 ID(15 和 28)正确的输出应该是:
| 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 |
非常感谢您的帮助。
我相信这只能通过递归 cte 来完成,因为 5 分钟 window 可以包含任意数量的行...前面 x 之间的 lead/lag/rows 将不起作用的情况。这是我的尝试:
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
我有一个 table 用于保存一些车辆事件,我需要每 5 分钟计算一次事件发生的次数。
样本:
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)
我能够通过以下查询获得结果:
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
查询结果:
| 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 |
上述结果的问题是查询排除了 ID(15 和 28)正确的输出应该是:
| 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 |
非常感谢您的帮助。
我相信这只能通过递归 cte 来完成,因为 5 分钟 window 可以包含任意数量的行...前面 x 之间的 lead/lag/rows 将不起作用的情况。这是我的尝试:
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