状态的平均持续时间 - 差距和离岛

时间:2018-05-31 12:06:17

标签: sql sql-server gaps-and-islands

我试图计算一件处于REPAIR状态的设备的平均周转时间。

我能够创建一个查询,其中包含每天都有快照状态的设备列表。

+-----------------+--------------+--------+----------------------+------------+------------------+
| equipmentNumber | snapshotDate | status | previousSnapshotDate | prevStatus | statusChangeFlag |
+-----------------+--------------+--------+----------------------+------------+------------------+
|          123456 | 2018-04-29   | ONHIRE | 2018-04-28           | AVAILABLE  |                1 |
|          123456 | 2018-04-30   | ONHIRE | 2018-04-29           | ONHIRE     |                0 |
|          123456 | 2018-05-01   | ONHIRE | 2018-04-30           | ONHIRE     |                0 |
|          123456 | 2018-05-02   | REPAIR | 2018-05-01           | ONHIRE     |                1 |
|          123456 | 2018-05-03   | REPAIR | 2018-05-02           | REPAIR     |                0 |
|          123456 | 2018-05-04   | ONHIRE | 2018-05-03           | REPAIR     |                1 |
|          654321 | 2018-04-30   | REPAIR | 2018-04-29           | AVAILABLE  |                1 |
|          654321 | 2018-05-01   | REPAIR | 2018-04-30           | REPAIR     |                0 |
|          654321 | 2018-05-02   | REPAIR | 2018-05-01           | REPAIR     |                0 |
+-----------------+--------------+--------+----------------------+------------+------------------+

所以,在这个例子中,我们有2台设备," 123456"在5/2和5/3处于2天的维修状态," 654321"在4月30日,5月1日和5月2日处于REPAIR状态3天。这将是平均修复周转时间(2 + 3)/ 2 = 2.5天。

我尝试了这种算法(Detect consecutive dates ranges using SQL),但它似乎并不能满足我的需求。

2 个答案:

答案 0 :(得分:1)

我尝试使用Incrementing ID列回答Gaps和Islands,如果不存在则创建一个,以及CREATE TABLE T1 ([equipmentNumber] int, [snapshotDate] datetime, [status] varchar(6), [previousSnapshotDate] datetime, [prevStatus] varchar(9), [statusChangeFlag] int) ; INSERT INTO T1 ([equipmentNumber], [snapshotDate], [status], [previousSnapshotDate], [prevStatus], [statusChangeFlag]) VALUES (123456, '2018-04-29 00:00:00', 'ONHIRE', '2018-04-28 00:00:00', 'AVAILABLE', 1), (123456, '2018-04-30 00:00:00', 'ONHIRE', '2018-04-29 00:00:00', 'ONHIRE', 0), (123456, '2018-05-01 00:00:00', 'ONHIRE', '2018-04-30 00:00:00', 'ONHIRE', 0), (123456, '2018-05-02 00:00:00', 'REPAIR', '2018-05-01 00:00:00', 'ONHIRE', 1), (123456, '2018-05-03 00:00:00', 'REPAIR', '2018-05-02 00:00:00', 'REPAIR', 0), (123456, '2018-05-04 00:00:00', 'ONHIRE', '2018-05-03 00:00:00', 'REPAIR', 1), (654321, '2018-04-30 00:00:00', 'REPAIR', '2018-04-29 00:00:00', 'AVAILABLE', 1), (654321, '2018-05-01 00:00:00', 'REPAIR', '2018-04-30 00:00:00', 'REPAIR', 0), (654321, '2018-05-02 00:00:00', 'REPAIR', '2018-05-01 00:00:00', 'REPAIR', 0) ; ;WITH cteX AS( SELECT Id = ROW_NUMBER()OVER(ORDER BY T.equipmentNumber, T.snapshotDate) ,T.equipmentNumber ,T.snapshotDate ,T.[status] ,T.previousSnapshotDate ,T.prevStatus ,T.statusChangeFlag FROM dbo.T1 T ),cteIsland AS( SELECT Island = X.Id - ROW_NUMBER()OVER(ORDER BY X.Id) ,* FROM cteX X WHERE X.[status] = 'REPAIR' ) SELECT * FROM cteIsland 窗口函数

Island

请注意Island Id equipmentNumber status 3 4 123456 REPAIR 3 5 123456 REPAIR 4 7 654321 REPAIR 4 8 654321 REPAIR 4 9 654321 REPAIR

Island

使用;WITH cteX AS( SELECT Id = ROW_NUMBER()OVER(ORDER BY T.equipmentNumber, T.snapshotDate) ,T.equipmentNumber ,T.snapshotDate ,T.[status] ,T.previousSnapshotDate ,T.prevStatus ,T.statusChangeFlag FROM dbo.T1 T ),cteIsland AS( SELECT Island = X.Id - ROW_NUMBER()OVER(ORDER BY X.Id) ,* FROM cteX X WHERE X.[status] = 'REPAIR' ) SELECT AvgDuration =SUM(Totals.IslandCounts) / (COUNT(Totals.IslandCounts) * 1.0) FROM ( SELECT IslandCounts = COUNT(I.Island) ,I.equipmentNumber FROM cteIsland I GROUP BY I.equipmentNumber ) Totals 列,您可以获得此TSQL所需的答案

AvgDuration
2.50000000000000

答案

getChildComponents(children) {
    return children.length > 1 ? (
        children.map((child, index) => (
            <ChildComponent key={`child-component-${index}`}>
                {child}
            </ChildComponent>
        ))
    ) : (
        <ChildComponent>{children}</ChildComponent>
    );
}

这是SQLFiddle

答案 1 :(得分:0)

该方法应该用于识别修复期:

select equipmentNumber, min(snapshotDate), max(snapshotDate)
from (select t.*,
             row_number() over (partition by equipmentNumber order by snapshotDate) as seqnum
      from t
     ) t
where status = 'REPAIR'
group by equipmentNumber, dateadd(day, - seqnum, snapshotDate);

您可以使用子查询获得平均值:

select avg(datediff(day, minsd, maxsd) * 1.0)
from (select equipmentNumber, min(snapshotDate) as minsd, max(snapshotDate) as maxsd
      from (select t.*,
                   row_number() over (partition by equipmentNumber order by snapshotDate) as seqnum
            from t
           ) t
      where status = 'REPAIR'
      group by equipmentNumber, dateadd(day, - seqnum, snapshotDate)
     ) e;