“服务器”每天处于“In”状态的总持续时间

Ash*_*Jha 5 sql-server sql-server-2008-r2

我有一个月内每天的服务器启动和停止时间的数据。我需要的结果包含当天的第一次开始时间、当天的最后一次停止时间、服务器在当天启动的总时间、每台服务器和每一天。

数据样本:

Date & Time           Reader ServerID
3/14/2016 6:36:20 AM    IN    123
3/14/2016 6:58:45 AM    OUT   123
3/14/2016 8:06:19 AM    IN    123
3/14/2016 9:32:48 AM    OUT   123
3/15/16 6:00:00 AM      IN    123
3/15/16 6:01:00 AM      OUT   123
3/14/2016 9:46 AM       IN    124
3/14/2016 10:01 AM      OUT   124
3/14/16 11:01 AM        IN    124
3/14/16 12:01 PM        OUT   124
Run Code Online (Sandbox Code Playgroud)

预期输出:

ServerID  FirstIN  Last Out  TotalInTime (min)  Date
123       6:00     09:32     86                 3/14
123       06:00    06:01     1                  3/15
124       9:46     12:01     75                 3/14
Run Code Online (Sandbox Code Playgroud)

请注意,每个在源表中IN总会有一个对应OUT的。

我该如何解决这个问题?

下面是 CREATE TABLE 和 INSERT 语句:

create table tbl1 (
    serverid numeric (18,0)
    , Reader varchar (20)
    , Date_Time datetime
);
Insert into tbl1 values (123, 'In', '2015-08-24 06:00:00.000');
Insert into tbl1 values (123, 'Out', '2015-08-24 07:00:00.000');
Insert into tbl1 values (123, 'In', '2015-08-24 08:00:00.000');
Insert into tbl1 values (123, 'Out', '2015-08-24 09:00:00.000');
Insert into tbl1 values (123, 'In', '2015-08-24 10:00:00.000');
Insert into tbl1 values (123, 'Out', '2015-08-24 11:00:00.000');
Insert into tbl1 values (123, 'In', '2015-08-25 10:00:00.000');
Insert into tbl1 values (123, 'Out', '2015-08-25 11:00:00.000');
Insert into tbl1 values (124, 'In', '2015-08-24 06:15:00.000');
Insert into tbl1 values (124, 'Out', '2015-08-24 07:30:00.000');
Insert into tbl1 values (124, 'In', '2015-08-24 08:00:00.000');
Insert into tbl1 values (124, 'Out', '2015-08-24 09:30:00.000');
Insert into tbl1 values (124, 'In', '2015-08-24 10:00:00.000');
Insert into tbl1 values (124, 'Out', '2015-08-24 11:30:00.000'); 
Run Code Online (Sandbox Code Playgroud)

Han*_*non 3

由于您确定源数据始终可靠,因此您可以使用:

;WITH src AS
(
    SELECT t1.ServerID
        , [Date] = DATEADD(DAY, 0, DATEDIFF(DAY, 0, t1.InDate))
        , t1.InDate
        , OutDate = (
        SELECT TOP(1) OutDate = al.DateAndTime
        FROM dbo.tbl1 al
        WHERE al.Reader = 'OFF'
            AND al.ServerID = t1.ServerID
            AND al.DateAndTime > t1.InDate
        ORDER BY al.DateAndTime
        )
    FROM (
        SELECT al.ServerID
            , al.Reader
            , InDate = al.DateAndTime
        FROM dbo.tbl1 al
        WHERE al.Reader = 'ON'
        ) t1
)
, src2 AS
(
    SELECT *
        , Duration = DATEDIFF(MINUTE, src.InDate, src.OutDate)
    FROM src
)
SELECT src2.ServerID
    , src2.Date
    , FirstIn = MIN(src2.InDate)
    , LastOut = MAX(src2.OutDate)
    , Duration = SUM(src2.Duration)
FROM src2
GROUP BY src2.ServerID
    , src2.Date
ORDER BY src2.ServerID
    , src2.Date;
Run Code Online (Sandbox Code Playgroud)

输出(我使用了第一组示例数据,因为您最初没有提供语句INSERT):

在此输入图像描述

此代码会折叠源表,以便每一行都有一个“入”和“出”日期,这使我们能够使用该DATEDIFF函数来计算持续时间。

这一行[Date] = DATEADD(DAY, 0, DATEDIFF(DAY, 0, t1.InDate))从 中去除了时间部分InDate,因此我们可以使用它来显示每台服务器每天一行。这可以作为计算的持久列移到表定义中。表定义为:

CREATE TABLE dbo.tbl1
(
    DateAndTime DATETIME NOT NULL
    , Reader CHAR(3) NOT NULL
    , ServerID INT NOT NULL
    , DateOnly AS DATEADD(DAY, 0, DATEDIFF(DAY, 0, DateAndTime))
        PERSISTED
);
Run Code Online (Sandbox Code Playgroud)