1

我有下表:

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

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

4

2 回答 2

1

您需要从一个包含所有分钟数的计数表中选择并 LEFT JOIN 到您的 ApplicationSessionHistory 表中:

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;
于 2018-09-12T13:25:47.113 回答
1

我会用 CTE 计数表来做到这一点。请注意,我在示例数据中添加了一个额外的 Session。

这是一个演示

--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
于 2018-09-12T13:27:08.963 回答