Reputation: 404
Lets say I have a simple table like so
Session
id dtmStarted dtmEnded
At the minute level I want to know the max number of concurrent sessions over a time-span
such that
id dtmStarted dtmEnded
1 - '2020-01-01 10:00' - '2020-01-01 10:05'
2 - '2020-01-01 10:00' - '2020-01-01 10:05'
3 - '2020-01-01 10:00' - '2020-01-01 10:05'
4 - '2020-01-01 10:06' - '2020-01-01 10:09'
5 - '2020-01-01 10:07' - '2020-01-01 10:08'
6 - '2020-01-01 10:10' - '2020-01-01 10:11'
So between 10:10 and 10:11 there was only 1 session. Between 10:07 and 10:08 there where 2 concurrent sessions. Between 10:00 - 10:01 there is 3 concurrent session and so forth. In this case the query should return 3.
Upvotes: 1
Views: 523
Reputation: 22811
You need a tally table for that. I create it here on the fly but it preferably may be instantiated as a regular table as well.
declare @t table(
id int,
dtmStarted datetime,
dtmEnded datetime
);
insert @t values
(1, '2020-01-01 10:00', '2020-01-01 10:05'),
(2, '2020-01-01 10:00', '2020-01-01 10:05'),
(3, '2020-01-01 10:00', '2020-01-01 10:05'),
(4, '2020-01-01 10:06', '2020-01-01 10:09'),
(5, '2020-01-01 10:07', '2020-01-01 10:08'),
(6, '2020-01-01 10:10', '2020-01-01 10:11');
declare @s datetime = '2020-01-01 10:00';
declare @e datetime = '2020-01-01 11:00';
-- table of 1000 numbers starting 0
with t0(n) as (
select n
from (
values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10)
) t(n)
),nmbs as(
select row_number() over(order by t1.n) - 1 n
from t0 t1, t0 t2, t0 t3
)
select dateadd(minute, n, @s) start, count(id) cnt
from nmbs
left join @t on dtmStarted <= dateadd(minute, n+1, @s) and dateadd(minute, n, @s)<= dtmEnded
where dateadd(minute, n+1, @s) <= @e
group by dateadd(minute, n, @s)
order by dateadd(minute, n, @s);
Returns
2020-01-01 10:01:00.000 3
2020-01-01 10:02:00.000 3
2020-01-01 10:03:00.000 3
2020-01-01 10:04:00.000 3
2020-01-01 10:05:00.000 4
2020-01-01 10:06:00.000 2
2020-01-01 10:07:00.000 2
2020-01-01 10:08:00.000 2
2020-01-01 10:09:00.000 2
2020-01-01 10:10:00.000 1
2020-01-01 10:11:00.000 1
2020-01-01 10:12:00.000 0
2020-01-01 10:13:00.000 0
2020-01-01 10:14:00.000 0
2020-01-01 10:15:00.000 0
...
2020-01-01 10:59:00.000 0
Probably you'll need to change both or one of predicates dtmStarted <= dateadd(minute, n+1, @s) and dateadd(minute, n, @s) <= dtmEnded
from <=
to strict <
to get the expected result.
Upvotes: 1