2017-01-16 42 views
4

我有一個SQL Server 2012表,其中包含會話和2的開始和結束時間。我現在需要知道每分鐘有多少會話已激活,這意味着> = starttime和< = endtime。計算具有兩列和每分鐘的行

Order_strUserId | Order_dtmInitiated  | Order_dtmLastUpdated 
s2ir1f8vqx  | 2016-12-13 15:06:17.993 | 2016-12-13 15:06:59.723 
4839m6lnjchn | 2016-12-13 15:09:42.807 | 2016-12-13 15:12:21.220 
y7k3u6q1wjn  | 2016-12-13 15:11:40.173 | 2016-12-13 15:12:01.630 
sdc74a0ahid  | 2016-12-13 15:14:06.013 | 2016-12-13 15:14:28.703 
2pgj2ixpta9  | 2016-12-13 15:17:41.567 | 2016-12-13 15:17:42.063 
qlfv4vmxdb  | 2016-12-13 15:18:17.750 | 2016-12-13 15:18:47.227 
y9jd24i59x5v | 2016-12-13 15:19:30.160 | 2016-12-13 15:19:30.607 
9vb2d6u90hn  | 2016-12-13 15:22:09.257 | 2016-12-13 15:22:09.743 

行1只爲2016年12月13日15點06計數,行2,每分鐘之間2016年12月13日15時09分和2016年12月13日15:12等。

我需要的是像

Time    | ActiveSessions 
2016-12-13 15:06 | 1 
2016-12-13 15:09 | 1 
2016-12-13 15:10 | 1 
2016-12-13 15:11 | 2 
2016-12-13 15:12 | 2 

如何做到這一點?

到目前爲止,我的想法一直是以分鐘計算UserId,然後將計數所需的時間加上。但我不知道如何計算這個。

SELECT COUNT(t.UserSessionId) , 
    DATEPART(yyyy , t.TimeInitiated) AS 'Year', 
    DATEPART(MM, t.TimeInitiated) 'Month', 
    DATEPART(DD, t.TimeInitiated) 'Day', 
    DATEPART(HH, t.TimeInitiated) 'Hour', 
    DATEPART(MI, t.TimeInitiated) 'Minute', 
    t.TimeNeeded 
FROM (SELECT DATEDIFF(MI, Order_dtmInitiated, Order_dtmLastUpdated) AS 'TimeNeeded', 
     Order_strUserId AS 'UserSessionId', 
     Order_dtmInitiated AS 'TimeInitiated' 
    FROM tblOrder) t 
GROUP BY DATEPART(yyyy , t.TimeInitiated), DATEPART(MM, t.TimeInitiated), DATEPART(DD, t.TimeInitiated), DATEPART(HH, t.TimeInitiated), DATEPART(MI, t.TimeInitiated), t.TimeNeeded 
+0

需要小的修改,你能解釋一下舉出更多的例子活動會話,並添加SQL的版本使用的是 – TheGameiswar

+0

會話是積極的「Order_dtmInitiated和Order_dtmLastUpdated」之間。我們使用的是 Microsoft SQL Server Management Studio v11.0.5058.0 – Shade

回答

0

使用日曆表,左連接數據

with Numbers as 
(
select 0 as NN 
union all 
select NN+1 
from Numbers 
where NN < 99999 
) 
, Cal_table as 
(
select dateadd(MI, NN, @StartTime) as By_Minute -- Throwing these in as parameters, but you can use a query to fill this bit in 
from Numbers 
where dateadd(MI, NN, @StartTime) <= @EndTime -- Throwing these in as parameters, but you can use a query to fill this bit in 
) 
select By_Minute, count(Order_strUserId) as ActiveUsers 
from Cal_Table 
left join MyTable 
on Order_dtmInitiated <= By_Minute 
and Order_dtmLastUpdated >= By_Minute 
3

您需要分鐘

;WITH cte 
    AS (SELECT Min(Cast(Dateadd(minute, Datediff(minute, 0, Order_dtmInitiated), 0) AS SMALLDATETIME)) AS st_date, 
       Max(Cast(Dateadd(minute, Datediff(minute, 0, Order_dtmLastUpdated), 0) AS SMALLDATETIME)) ed_date 
     FROM Yourtable 
     UNION ALL 
     SELECT Dateadd(minute, 1, st_date), 
       ed_date 
     FROM cte 
     WHERE st_date < ed_date) 
SELECT st_date, 
     Count(1) 
FROM cte a 
     LEFT JOIN Yourtable b 
       ON a.st_date >= Cast(Dateadd(minute, Datediff(minute, 0, Order_dtmInitiated), 0) AS SMALLDATETIME) 
       AND a.st_date <= Cast(Dateadd(minute, Datediff(minute, 0, Order_dtmLastUpdated), 0) AS SMALLDATETIME) 
GROUP BY st_date 
OPTION (maxrecursion 0) 

我已經使用Recursive CTE生成日期的日曆表,但我希望創建一個Calendar表在我的數據庫中,並用它在這樣的查詢

0

您可以用遞歸CTE是開始於爲每個會話行的第一分鐘做到這一點,增加了一分鐘,直到達到該會話行結束,再算上每時間戳會議:

-- Setup data: 

DECLARE @rows TABLE(UserId VARCHAR(20), Initiated DATETIME, LastUpdated DATETIME) 
INSERT INTO @rows VALUES 
    ('s2ir1f8vqx' , '2016-12-13 15:06:17.993', '2016-12-13 15:06:59.723'), 
    ('4839m6lnjchn', '2016-12-13 15:09:42.807', '2016-12-13 15:12:21.220'), 
    ('y7k3u6q1wjn' , '2016-12-13 15:11:40.173', '2016-12-13 15:12:01.630'), 
    ('sdc74a0ahid' , '2016-12-13 15:14:06.013', '2016-12-13 15:14:28.703'), 
    ('2pgj2ixpta9' , '2016-12-13 15:17:41.567', '2016-12-13 15:17:42.063'), 
    ('qlfv4vmxdb' , '2016-12-13 15:18:17.750', '2016-12-13 15:18:47.227'), 
    ('y9jd24i59x5v', '2016-12-13 15:19:30.160', '2016-12-13 15:19:30.607'), 
    ('9vb2d6u90hn' , '2016-12-13 15:22:09.257', '2016-12-13 15:22:09.743') 

-- Do the work: 

;WITH activity AS 
(
    SELECT r1.UserId, CAST(CONVERT(CHAR(17), r1.Initiated, 113) AS DATETIME) AS dt FROM @rows r1 
    UNION ALL 
    SELECT r2.UserId, DATEADD(minute, 1, dt) AS dt FROM activity INNER JOIN @rows r2 ON r2.UserId = activity.UserId WHERE DATEADD(minute, 1, dt) <= r2.LastUpdated 
) 
SELECT dt as Time, count(UserId) as ActiveSessions FROM activity 
GROUP BY dt 
OPTION (MAXRECURSION 10080) -- 10080 = 7*24*60 = user active every minute of one consecutive week (max is 32767 or ~ 3 weeks) 

輸出:

Time      ActiveSessions 
2016-12-13 15:06:00.000  1 
2016-12-13 15:09:00.000  1 
2016-12-13 15:10:00.000  1 
2016-12-13 15:11:00.000  2 
2016-12-13 15:12:00.000  2 
2016-12-13 15:14:00.000  1 
2016-12-13 15:17:00.000  1 
2016-12-13 15:18:00.000  1 
2016-12-13 15:19:00.000  1 
2016-12-13 15:22:00.000  1 
0

其他方式,無需CTE或日曆表。只是理念,以滿足您的需求

DECLARE 
    @dt_from DATETIME = '2016-12-13 15:06:17.993' 
    ,@dt_to  DATETIME = '2016-12-13 15:22:09.743' 
    ,@cnt  INT 
    ,@mins  INT   = 2; 

DECLARE @result TABLE([Time] DATETIME, [ActiveSessions] INT); 

SET @dt_from = DATEADD(mi, DATEDIFF(mi, 0, @dt_from), 0); 
SET @dt_to  = DATEADD(mi, DATEDIFF(mi, 0, @dt_to),  0); 

WHILE @dt_from <= @dt_to 
BEGIN 

    SELECT @cnt = COUNT(*) FROM [YourTable] 
    WHERE 
     DATEADD(mi, DATEDIFF(mi, 0, [Order_dtmInitiated]),  0) BETWEEN @dt_from AND DATEADD(mi, @mins, @dt_from) 
    OR DATEADD(mi, DATEDIFF(mi, 0, [Order_dtmLastUpdated]), 0) BETWEEN @dt_from AND DATEADD(mi, @mins, @dt_from) 

    INSERT INTO @result([Time], [ActiveSessions]) 
    VALUES (@dt_from, @cnt); 

    SET @dt_from = DATEADD(mi, @mins, @dt_from); 
END; 

SELECT * FROM @result;