sql-servert-sqlkpi

Calculate MTTF with SQL query


I'm trying to calculate the expected average time between the end of a fault and the beginning of the next one (two separate columns) [MTTF].

MTTF = Mean Time To Failure: is the average time from the end of a fault to the beginning of the next

I have already asked a similar question and I have been answered very professionally. I love this forum.

I have to calculate the difference between the dates in the Failure column and in the End_Of_Repair column for each row -1 (another column), transforming it into hours and dividing it by the number of intervals to calculate the average time.

Intervals = number of rows - 1

This is my table:

Failure                 |Start_Repair            |End_Of_Repair           |Line     |Operator
------------------------|------------------------|------------------------|---------|--------
2019-06-26 06:30:00     |2019-06-26 10:40:00     |2019-06-27 12:00:00     |A        |Mike
2019-06-28 00:10:00     |2019-06-28 02:40:00     |2019-06-29 01:12:00     |A        |Loty
2019-06-30 10:10:00     |2019-06-30 02:40:00     |2019-07-01 00:37:00     |B        |Judy
2019-07-02 12:01:00     |2019-07-02 14:24:00     |2019-07-05 00:35:00     |B        |Judy
2019-07-06 07:08:00     |2019-07-06 15:46:00     |2019-07-07 02:30:00     |A        |Mike
2019-07-07 08:22:00     |2019-07-08 05:19:00     |2019-07-08 08:30:00     |B        |Loty
2019-07-29 04:10:00     |2019-07-29 07:40:00     |2019-07-29 14:00:05     |A        |Judy

So I have to make the difference on the error and end of error columns, the second minus the first, the third minus the second, etc. Divided by the calculated intervals (which are the number of lines-1 since I start from line 2-line 1).

In a nutshell, an average-cross between two tables.

I attach the image to make the idea better.

enter image description here

So I'll have to do the seventh line of the failure column minus the sixth row of the end_of_repair column, sixth row of failure minus the fifth row of end_of_repair column and so on until you get to the first.

I tought:

SELECT line,
DATEDIFF(hour, min(End_Of_Repair), max (Failure)) /  nullif(count(*) - 1, 0) as 'intervals'
from Test_Failure
group by line

But the results are:

A = 253
B = 76

The result should come back

A = (12,1+173,93+529,6) / 3 = 238h

B = (35,4 + 55,78) / 2 = 45,59h


Solution

  • One method would be to use LAG to get the value from the previous row; then you can average the difference in hours between the 2 times:

    WITH CTE AS(
        SELECT V.Failure,
               V.Start_Repair,
               V.End_Of_Repair,
               V.Line,
               V.Operator,
               LAG(V.End_Of_Repair) OVER (PARTITION BY V.Line ORDER BY V.Failure) AS LastRepair
        FROM (VALUES('2019-06-26T06:30:00','2019-06-26T10:40:00','2019-06-27T12:00:00','A ','Mike'),
                    ('2019-06-28T00:10:00','2019-06-28T02:40:00','2019-06-29T01:12:00','A ','Loty'),
                    ('2019-06-30T10:10:00','2019-06-30T02:40:00','2019-07-01T00:37:00','B ','Judy'),
                    ('2019-07-02T12:01:00','2019-07-02T14:24:00','2019-07-05T00:35:00','B ','Judy'),
                    ('2019-07-06T07:08:00','2019-07-06T15:46:00','2019-07-07T02:30:00','A ','Mike'),
                    ('2019-07-07T08:22:00','2019-07-08T05:19:00','2019-07-08T08:30:00','B ','Loty'),
                    ('2019-07-29T04:10:00','2019-07-29T07:40:00','2019-07-29T14:00:05','A ','Judy'))V(Failure, Start_Repair, End_Of_Repair, Line, Operator))
    SELECT CTE.Line,
           AVG(DATEDIFF(HOUR, CTE.LastRepair, CTE.Failure)) AS FaultHours
    FROM CTE
    GROUP BY CTE.Line;