Table Device_Status
Id | Status | Timestamp |
---|---|---|
1 | Active | 2023-01-13T18.00.01.0187528 |
2 | Active | 2023-01-13T18.00.01.0187529 |
1 | Failed | 2023-01-13T18.00.01.0187530 |
3 | Active | 2023-01-13T18.00.01.0187531 |
1 | Failed | 2023-01-13T18.00.01.0187532 |
1 | Active | 2023-01-13T18.00.01.0187533 |
3 | Active | 2023-01-13T18.00.01.0187534 |
1 | Failed | 2023-01-13T18.00.01.0187535 |
4 | Failed | 2023-01-13T18.00.01.0187536 |
1 | Active | 2023-01-13T18.00.01.0187537 |
Expected Output (Need SQL query to generate):
ID | Fail_Begin | Fail_End |
---|---|---|
1 | 2023-01-13T18.00.01.0187530 | 2023-01-13T18.00.01.0187532 |
1 | 2023-01-13T18.00.01.0187535 | 2023-01-13T18.00.01.0187535 |
4 | 2023-01-13T18.00.01.0187536 | 2023-01-13T18.00.01.0187536 |
Basically, for each ID get min (timestamp) and max (timestamp) but over continuous records for that ID. If there is only one record, then min=max as is the case with the second and third record in the sample result set.
I have tried this (and various subquery variants thereof)
SELECT Id, min(Timestamp) AS Fail_Begin, max(Timestamp) AS Fail_EndFROM Device_StatusGROUP BY Id
but need to group by only continuously occurring records,
So perhaps by adding a notion of status change first would help? Starting with zero as initial status and then incrementing the change code by 1 every time the next record is different in order to thereby generate an intermediate result like so...
Table Device_Status_With_Change_Column
Id | Status | Change | Timestamp |
---|---|---|---|
1 | Active | 0 | 2023-01-13T18.00.01.0187528 |
2 | Active | 0 | 2023-01-13T18.00.01.0187529 |
1 | Failed | 1 | 2023-01-13T18.00.01.0187530 |
3 | Active | 0 | 2023-01-13T18.00.01.0187531 |
1 | Failed | 1 | 2023-01-13T18.00.01.0187532 |
1 | Active | 2 | 2023-01-13T18.00.01.0187533 |
3 | Active | 0 | 2023-01-13T18.00.01.0187534 |
1 | Failed | 3 | 2023-01-13T18.00.01.0187535 |
4 | Failed | 0 | 2023-01-13T18.00.01.0187536 |
1 | Active | 4 | 2023-01-13T18.00.01.0187537 |
And then doing
SELECT Id, Change, min(Timestamp) AS Fail_Begin, max(Timestamp) AS Fail_EndFROM Device_Status_With_Change_ColumnGROUP BY Id, Change
Other than looping over the result set in a programming language, I do not yet see a direct SQL statement that would do this in one fell swoop without the intermediate table and I do not see how to compute the column Change (in SQL).