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)
由于您确定源数据始终可靠,因此您可以使用:
;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)