Find number of concurrent users in a SQL records

后端 未结 7 1024
生来不讨喜
生来不讨喜 2021-01-31 21:54

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-12T1         


        
7条回答
  •  轻奢々
    轻奢々 (楼主)
    2021-01-31 22:20

    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.

提交回复
热议问题