SQL Server-显示时间范围内每分钟的活动会话数

时间:2018-09-12 13:14:55

标签: sql-server

我有下表:

SessionID | UserName | Started             | Ended
----------------------------------------------------------------
100         Test1      2015-07-26 00:03:05   2015-07-26 00:08:12

正如标题所说,我需要在给定的@FromDate@ToDate参数之间,每分钟提取多少活动会话。到目前为止,我尝试过的操作不会选择非活动会话(当该分钟内没有客户在线时),我无法弄清楚该怎么做。

我的SQL语句

CREATE PROCEDURE [dbo].[ActiveSessionsByMinute]  @FromDate datetime, @ToDate datetime

AS
BEGIN

SET NOCOUNT ON


SELECT DATEADD(MINUTE, DATEPART(MINUTE, Started), CAST(CONVERT(varchar(20), Started, 112) AS datetime)) AS DateMinute,
COUNT(SessionID) AS ActiveSessions
FROM ApplicationSessionHistory
GROUP BY DATEADD(MINUTE, DATEPART(MINUTE, Started), CAST(CONVERT(varchar(20), Started, 112) AS datetime))


END

GO

输出

DateMinute              |  ActiveSessions
-----------------------------------------
2015-07-26 00:03:00.000 |  1

如果执行以下语句,则应该获得所需的输出(如下):

EXEC dbo.ActiveSessionsByMinute 
@FromDate = '2015-07-26 00:00', 
@ToDate = '2015-07-26 00:10'

所需的输出

DateMinute              |  ActiveSessions
-----------------------------------------
2015-07-26 00:00:00.000 |  0
2015-07-26 00:01:00.000 |  0
2015-07-26 00:02:00.000 |  0
2015-07-26 00:03:00.000 |  1
2015-07-26 00:04:00.000 |  1
2015-07-26 00:05:00.000 |  1
2015-07-26 00:06:00.000 |  1
2015-07-26 00:07:00.000 |  1
2015-07-26 00:08:00.000 |  1
2015-07-26 00:09:00.000 |  0
2015-07-26 00:00:00.000 |  0

有人可以给我小费吗?谢谢

2 个答案:

答案 0 :(得分:1)

您将希望从带有所有分钟数的计数表中进行选择,并向应用程序会话历史表中左移:

CREATE PROCEDURE [dbo].[ActiveSessionsByMinute]
    @FromDate DATETIME
  , @ToDate DATETIME
AS
BEGIN

    SET NOCOUNT ON;


    SELECT allminutes.alltimes AS DateMinute
         , COUNT(SessionID) AS ActiveSessions
    FROM
    (
        SELECT DATEADD(MINUTE, myrows.rn, @FromDate) AS alltimes
        FROM
        (
            SELECT ROW_NUMBER() OVER (ORDER BY s.id) - 1 rn
            FROM master.sys.syscolumns AS s
        ) myrows
    ) allminutes
        LEFT OUTER JOIN ApplicationSessionHistory ON allminutes.alltimes BETWEEN ApplicationSessionHistory.Started AND ApplicationSessionHistory.Ended
    WHERE allminutes.alltimes <= @ToDate
    GROUP BY DATEADD(MINUTE, DATEPART(MINUTE, Started), CAST(CONVERT(VARCHAR(20), Started, 112) AS DATETIME));

END;

答案 1 :(得分:1)

我将使用CTE理货表格来完成此操作。注意,我在示例数据中添加了一个额外的会话。

HERE IS A DEMO

--Sample data
declare @table table (SessionID int, UserName varchar(16), Started datetime, Ended datetime)
insert into @table
values
(100,'Test1','2015-07-26 00:03:05','2015-07-26 00:08:12')
,(101,'Test1','2015-07-26 00:04:05','2015-07-26 00:05:12')


--used as a beginning anchor for the tally table    
declare @startDate datetime = (select min(cast(Started as date)) from @table)

--take the original data, and truncate the seconds
;with NewTable as(
select 
    SessionID 
    ,UserName
    ,Started = CAST(DateAdd(minute, DateDiff(minute, 0, Started), 0) AS smalldatetime)
    ,Ended = CAST(DateAdd(minute, DateDiff(minute, 0, Ended), 0) AS smalldatetime)
from @table
    ),

    --tally table to get 10K minutes. 
    --This can be expanded for larger date ranges, and is faster than recursive CTE
    E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
    E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
    E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
    cteTally(N) AS 
    (
        SELECT  TallyDate = dateadd(minute,ROW_NUMBER() OVER (ORDER BY (SELECT NULL)),@startDate) FROM E4
    )


--use cross apply and and a case statement to find if it falls in the range
select
    DateMinute = N
    ,SessionID
    ,Started
    ,Ended
    ,IsActive = case when (Started <=N and Ended >= N) then 1 else 0 end
from NewTable t
cross apply cteTally 
where N <= (select max(Ended) from @table)
order by SessionID, N

对于求和部分,您可以简单地进行汇总。将最后一个SELECT替换为此

--based on the above output, just do the SUM
select
    DateMinute = N
    ,ActiveSessions = sum(case when (Started <=N and Ended >= N) then 1 else 0 end)
from NewTable t
cross apply cteTally 
where N <= (select max(dateadd(minute,1,Ended)) from @table)
group by N
order by N