I have the table of following structure:
UserID StartedOn EndedOn
1 2009-7-12T14:01 2009-7-12T15:01
2 2009-7-12T14:30 2009-7-12T14:45
3 2009-7-12T14:47 2009-7-12T15:30
4 2009-7-12T13:01 2009-7-12T17:01
5 2009-7-12T14:15 2009-7-12T18:01
6 2009-7-12T11:01 2009-7-12T19:01
1 2009-7-12T16:07 2009-7-12T19:01
I need to find the maximal number of concurrent users that were on line. In the above table the result would be 5 because users set1={1,2,4,5,6} and set2={1,3,4,5,6} were online in the same period.
Do you have an idea how one could calculate this using T-SQL only?
the sql command "sp_who" which provides information about current users, sessions, and processes in an instance of the Microsoft SQL Server Database Engine (MSDN) From here, you should be able to send the results into a temp table and group them by servername.
Calculating the Number of Concurrent Users For example, if your peak visits per hour is 200 visitors and the average visit duration is 6 minutes, the number of concurrent users that should be used to create 200 visits per hour is 20 concurrent users.
Answer: In SQL Server, there is a system view called sys. database_principals. You can run a query against this system view that returns all of the Users that have been created in SQL Server as well as information about these Users.
Every time the user logs in to the domain, a new RPAS server session is created for this user. These server sessions created by the same user who has logged in the same domain are called concurrent user sessions. Concurrent user sessions allow the same user to work on different workbooks at the same time.
Clearly the number of concurrent users only changes when a user either starts or ends a period, so it is enough to determine the number of concurrent users during starts and ends. So, reusing test data provided by Remus (thank you Remus):
DECLARE @Table TABLE
(
UserId int,
StartedOn datetime,
EndedOn datetime
);
insert into @table (UserId, startedOn, EndedOn)
select 1, '2009-7-12 14:01', '2009-7-12 15:01'
union all select 2, '2009-7-12 14:30', '2009-7-12 14:45'
union all select 3, '2009-7-12 14:47', '2009-7-12 15:30'
union all select 4, '2009-7-12 13:01', '2009-7-12 17:01'
union all select 5, '2009-7-12 14:15', '2009-7-12 18:01'
union all select 6, '2009-7-12 11:01', '2009-7-12 19:01'
union all select 1, '2009-7-12 16:07', '2009-7-12 19:01';
SELECT MAX(ConcurrentUsers) FROM(
SELECT COUNT(*) AS ConcurrentUsers FROM @table AS Sessions
JOIN
(SELECT DISTINCT StartedOn AS ChangeTime FROM @table
) AS ChangeTimes
ON ChangeTime >= StartedOn AND ChangeTime < EndedOn
GROUP BY ChangeTime
) AS ConcurrencyAtChangeTimes
-------
5
BTW using DISTINCT per se is not a mistake - only abusing DISTINCT is. DISTINCT is just a tool, using it in this context is perfectly correct.
Edit: I was answering the OP's question: "how one could calculate this using T-SQL only". Note that the question does not mention performance.
If the questions was this: "what is the fastest way to determine maximum concurrency if the data is stored in SQL Server", I would provide a different answer, something like this:
Consider the following alternatives
If the question was "what is the fastest way to determine maximum concurrency using a T-SQL query", I would probably not answer at all. The reason: if I needed really good performance, I would not solve this problem in a T-SQL query.
You can order all events on date order and compute a running aggregate of current users logged in:
DECLARE @Table TABLE
(
UserId int,
StartedOn datetime,
EndedOn datetime
);
insert into @table (UserId, startedOn, EndedOn)
select 1, '2009-7-12 14:01', '2009-7-12 15:01'
union all select 2, '2009-7-12 14:30', '2009-7-12 14:45'
union all select 3, '2009-7-12 14:47', '2009-7-12 15:30'
union all select 4, '2009-7-12 13:01', '2009-7-12 17:01'
union all select 5, '2009-7-12 14:15', '2009-7-12 18:01'
union all select 6, '2009-7-12 11:01', '2009-7-12 19:01'
union all select 1, '2009-7-12 16:07', '2009-7-12 19:01';
with cte_all_events as (
select StartedOn as Date
, +1 as Users
from @Table
union all
select EndedOn as Date
, -1 as Users
from @Table),
cte_ordered_events as (
select Date
, Users
, row_number() over (order by Date asc) as EventId
from cte_all_events)
, cte_agg_users as (
select Date
, Users
, EventId
, (select sum(Users)
from cte_ordered_events agg
where agg.EventId <= e.EventId) as AggUsers
from cte_ordered_events e)
select * from cte_agg_users
2009-07-12 11:01:00.000 1 1 1
2009-07-12 13:01:00.000 1 2 2
2009-07-12 14:01:00.000 1 3 3
2009-07-12 14:15:00.000 1 4 4
2009-07-12 14:30:00.000 1 5 5
2009-07-12 14:45:00.000 -1 6 4
2009-07-12 14:47:00.000 1 7 5
2009-07-12 15:01:00.000 -1 8 4
2009-07-12 15:30:00.000 -1 9 3
2009-07-12 16:07:00.000 1 10 4
2009-07-12 17:01:00.000 -1 11 3
2009-07-12 18:01:00.000 -1 12 2
2009-07-12 19:01:00.000 -1 13 1
2009-07-12 19:01:00.000 -1 14 0
Once you have this in place, finding the number of maximum concurrent sessions is trivial. As you see you have two moments when you had 5 users, at 14:30 (when user 2 logged in) and at 14:47 (when user 3 logged in). Just replace the last query that selects from the CTE to get the actual max:
select top(1) AggUsers
from cte_agg_users
order by AggUsers desc
This solution uses CTEs so it will only work on SQL 2k5, if you're still on SQL 2000 you'll have to rewrite it using derived tables instead of CTEs.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With