关联开始/停止日期并将其持续时间相加

时间:2017-12-08 16:31:39

标签: sql sql-server

更新:在底部我添加了预期输出和我设想的表

我的目标是两个相关的停机事件,以显示一个事件的原因及其造成的停机时间。

我有一个整体架构:

DECLARE @EquipmentDownTime TABLE
(
ID INT IDENTITY(1,1),
Equipment varchar(5),
Time DATETIME,
StartStop NVARCHAR(15)
)

所以记录如下:

 1, Motor, '18/8/2017 12:00:00', Stop 
 2, Motor, '18/8/2017 12:10:00', Start

我目前正在使用匹配对表功能来计算用户输入日期范围之间停机时间的总持续时间,但我想扩展功能,以根据这些持续时间说明事件导致另一个事件的持续时间。

我试图做的是关联另一件设备"停止"在上面的记录之间,然后确定它的总时间。使用以下示例数据:

INSERT INTO @EquipmentDownTime (Equipment, [Time], StartStop)
VALUES
  ('Motor', '20170812 12:00:00', 'Stop'), --ID 1
  ('Valve', '20170812 12:05:00', 'Stop'), --ID 2
  ('Motor', '20170812 12:30:00', 'Start'), --ID 3
  ('Valve', '20170812 13:05:00', 'Start'), --ID 4
  ('Motor', '20170812 14:00:00', 'Stop'), --ID 5
  ('Valve', '20170812 14:05:00', 'Stop'), --ID 6
  ('Motor', '20170812 15:30:00', 'Start'), --ID 7
  ('Valve', '20170812 15:05:00', 'Start'); --ID 8

在这种情况下,我会说ID 1导致ID 2停机1小时,因为它的停止在1到3之间,这是一个停止/启动对。

我想最终结果会是这样的:

 DECLARE @Causation TABLE
(
ID INT                     IDENTITY(1,1),
CauationEquipment          varchar(5),
CauationEquipmentShutdown  DATETIME,
AffectedEquipment          varchar(5),
AffectedEquipmentShutdown  DATETIME,
DurationOfAffectedEquip    INT
)

记录结果(因果ID和受影响,来自@EquipmentDowntime表中的Identity Id):

 1, Motor, '20170812 12:00:00', Valve, '20170812 12:05:00', 60
 2, Motor, '20170812 14:00:00', Valve, '20170812 14:05:00', 60

我在这里缺少的部分是有效地链接我认为使用while循环执行所有停机事件的相关性并抓住停止和下一次启动并将其存储在临时表中但它变得混乱。

SQL Server 2014

2 个答案:

答案 0 :(得分:2)

假设您使用的是SQL Server 2012+,并且单个停机时间只有2个条目(一个用于停止,一个用于开始):

WITH Downtime AS (
    SELECT *,
           LEAD([Time]) OVER (PARTITION BY Equipment ORDER BY [Time] ASC) AS NextStatus
    FROM @EquipmentDownTime)
SELECT ID,
       Equipment,
       DATEDIFF(MINUTE,[Time],NextStatus) AS Duration
FROM Downtime
WHERE StartStop = 'Stop';

答案 1 :(得分:0)

我扩展了Larnu提供的内容,这与我在问题中预期的输出相匹配:

DECLARE @EquipmentDownTime TABLE
(
ID INT IDENTITY(1,1),
Equipment varchar(5),
Time DATETIME,
StartStop NVARCHAR(15)
)

INSERT INTO @EquipmentDownTime (Equipment, [Time], StartStop)
VALUES
  ('Motor', '20170812 12:00:00', 'Stop'), --ID 1
  ('Valve', '20170812 12:05:00', 'Stop'), --ID 2
  ('Motor', '20170812 12:30:00', 'Start'), --ID 3
  ('Valve', '20170812 13:05:00', 'Start'), --ID 4
  ('Motor', '20170812 14:00:00', 'Stop'), --ID 5
  ('Valve', '20170812 14:05:00', 'Stop'), --ID 6 --
  ('Motor', '20170812 14:30:00', 'Start'), --ID 7
  ('Valve', '20170812 15:05:00', 'Start'); --ID 8

 ;WITH 
    Causation AS (
        SELECT ID,
        LAG(Equipment) OVER (ORDER BY [Time] ASC) AS LastEquipment,
        LAG([Time]) OVER (ORDER BY [Time] ASC) AS PrevEquipDownTime
        FROM @EquipmentDownTime
        ),
    Downtime AS (
        SELECT *,
        (LEAD([Time]) OVER (PARTITION BY Equipment ORDER BY [Time] ASC)) AS NextStatus
        FROM @EquipmentDownTime
        )
SELECT Downtime.ID,
       LastEquipment AS [CauationEquipment],
       PrevEquipDownTime AS [CauationEquipmentShutdown],
       Equipment   AS [Affected Equipment],
       Time AS [AffectedEquipmentShutdown],
       NextStatus,
       DATEDIFF(MINUTE,[Time],NextStatus) AS Duration
FROM Downtime 
JOIN Causation
ON   Downtime.ID = Causation.ID
WHERE StartStop = 'Stop'
AND Equipment = 'Valve'

输出:

2,  Motor,  2017-08-12 12:00:00.000,    Valve,  2017-08-12 12:05:00.000,    2017-08-12 13:05:00.000,    60
6,  Motor,  2017-08-12 14:00:00.000,    Valve,  2017-08-12 14:05:00.000,    2017-08-12 15:05:00.000,    60