Sql server 如何计算SQL Server中一列的两行之间的持续时间?
数据库中有这样的数据Sql server 如何计算SQL Server中一列的两行之间的持续时间?,sql-server,Sql Server,数据库中有这样的数据 ID Server DownTime ServerStatus --- ----------------------- ------------ 1 2012-03-30 00:00:00.000 1 2 2012-03-30 00:30:00.000 0 3 2012-03-30 01:00:00.000 0 4 2012-03-30 01:30:00.000 0 5 2012-03-30 02:00:00.000 1
ID Server DownTime ServerStatus
--- ----------------------- ------------
1 2012-03-30 00:00:00.000 1
2 2012-03-30 00:30:00.000 0
3 2012-03-30 01:00:00.000 0
4 2012-03-30 01:30:00.000 0
5 2012-03-30 02:00:00.000 1
6 2012-03-30 02:30:00.000 1
7 2012-03-30 03:00:00.000 0
8 2012-03-30 03:30:00.000 1
我需要一个查询或存储过程,将给我作为输出
Start Time EndTime TotalDownTimeinMinutes
------------ ------------ ----------------------
3/30/12 0:30 3/30/12 2:00 90
3/30/12 3:00 3/30/12 3:30 30
您可以使用此DDL测试上述查询
create table Tbl
(
ID int,
ServerDownTime datetime,
ServerStatus bit
)
insert Tbl select
1 ,'2012-03-30 00:00:00.000', 1 union all select
2 ,'2012-03-30 00:30:00.000', 0 union all select
3 ,'2012-03-30 01:00:00.000', 0 union all select
4 ,'2012-03-30 01:30:00.000', 0 union all select
5 ,'2012-03-30 02:00:00.000', 1 union all select
6 ,'2012-03-30 02:30:00.000', 1 union all select
7 ,'2012-03-30 03:00:00.000', 0 union all select
8 ,'2012-03-30 03:30:00.000', 1
或者,如果您在web上,但离SQL Server不远,则以下是此解决方案的基础:
基本思想是将行分组,从ServerStatus=0行开始,以ServerStatus=1行结束。例如,如果运行此查询,您将看到停机组(列GroupID)::
请将列的格式设置为实际列。。如果您还包括列类型,那就太棒了。谢谢您的更新。这对我真的很有帮助。我可以知道GROUP BY上面X的含义吗。@Linnet-FROM子句中的每个表或行源都必须有一个名称。引用表时,名称(默认情况下)为表的名称。使用子查询时,必须提供别名(在本例中为
X
)。然而,在本例中选择的名称并不重要-它可以是任何东西。@Richard aka cyberkiwi-非常感谢。
create table Tbl
(
ID int,
ServerDownTime datetime,
ServerStatus bit
)
insert Tbl select
1 ,'2012-03-30 00:00:00.000', 1 union all select
2 ,'2012-03-30 00:30:00.000', 0 union all select
3 ,'2012-03-30 01:00:00.000', 0 union all select
4 ,'2012-03-30 01:30:00.000', 0 union all select
5 ,'2012-03-30 02:00:00.000', 1 union all select
6 ,'2012-03-30 02:30:00.000', 1 union all select
7 ,'2012-03-30 03:00:00.000', 0 union all select
8 ,'2012-03-30 03:30:00.000', 1
DECLARE @MyTable TABLE (
ID INT PRIMARY KEY,
ServerDownTime DATETIME NOT NULL,
UNIQUE (ServerDownTime),
ServerStatus BIT NOT NULL
);
INSERT @MyTable (ID, ServerDownTime, ServerStatus)
SELECT 1,'2012-03-30T00:00:00',1 UNION ALL
SELECT 2,'2012-03-30T00:30:00',0 UNION ALL
SELECT 3,'2012-03-30T01:00:00',0 UNION ALL
SELECT 4,'2012-03-30T01:30:00',0 UNION ALL
SELECT 5,'2012-03-30T02:00:00',1 UNION ALL
SELECT 6,'2012-03-30T02:30:00',1 UNION ALL
SELECT 7,'2012-03-30T03:00:00',0 UNION ALL
SELECT 8,'2012-03-30T03:30:00',1;
WITH Base
AS
(
SELECT *, ROW_NUMBER() OVER(ORDER BY t.ServerDownTime) AS RowNum
FROM @MyTable t
), DownTimeGrouping
AS
(
SELECT crt.RowNum,
crt.ID,
crt.ServerDownTime,
crt.ServerStatus,
CASE WHEN crt.ServerStatus=0 THEN 1 END AS GroupID,
CASE WHEN crt.ServerStatus=0 THEN 1 ELSE 0 END AS LastGroupID
FROM Base crt
WHERE crt.RowNum=1
UNION ALL
SELECT crt.RowNum,
crt.ID,
crt.ServerDownTime,
crt.ServerStatus,
CASE
WHEN prev.ServerStatus=0 AND crt.ServerStatus IN(0,1) THEN prev.GroupID
WHEN prev.ServerStatus=1 AND crt.ServerStatus=0 THEN prev.LastGroupID+1
END AS GroupID,
CASE
WHEN prev.ServerStatus=0 AND crt.ServerStatus IN(0,1) THEN prev.GroupID
WHEN prev.ServerStatus=1 AND crt.ServerStatus=0 THEN prev.LastGroupID+1
WHEN prev.ServerStatus=1 AND crt.ServerStatus=1 THEN prev.GroupID
END AS LastGroupID
FROM Base crt
INNER JOIN DownTimeGrouping prev ON crt.RowNum=prev.RowNum+1
)
SELECT *, DATEDIFF(MINUTE,x.StartTime,x.EndTime) AS MinutesDiff
FROM (
SELECT t.GroupID, MIN(t.ServerDownTime) AS StartTime, MAX(t.ServerDownTime) AS EndTime
FROM DownTimeGrouping t
WHERE t.GroupID IS NOT NULL
GROUP BY t.GroupID
) x
WITH Base
AS
(...), DownTimeGrouping
AS
(...)
SELECT *
FROM DownTimeGrouping g
ORDER BY g.RowNum
RowNum ID ServerDownTime ServerStatus GroupID LastGroupID
-------------------- ----------- ----------------------- ------------ ----------- -----------
1 1 2012-03-30 00:00:00.000 1 NULL 0
2 2 2012-03-30 00:30:00.000 0 1 1
3 3 2012-03-30 01:00:00.000 0 1 1
4 4 2012-03-30 01:30:00.000 0 1 1
5 5 2012-03-30 02:00:00.000 1 1 1
6 6 2012-03-30 02:30:00.000 1 NULL 1
7 7 2012-03-30 03:00:00.000 0 2 2
8 8 2012-03-30 03:30:00.000 1 2 2