Reputation: 3837
Row Status Time
1 Status1 1383264075
2 Status1 1383264195
3 Status1 1383264315
4 Status2 1383264435
5 Status2 1383264555
6 Status2 1383264675
7 Status2 1383264795
8 Status1 1383264915
9 Status3 1383265035
10 Status3 1383265155
11 Status2 1383265275
12 Status3 1383265395
13 Status1 1383265515
14 Status1 1383265535
15 Status2 1383265615
The [Time]
column holds POSIX time
I want to be able to calculate the number of seconds a given [Status]
is active for within a given time period without using CURSORS. If this is the only then that is fine as I've already done that.
Using the above sample data extract, how do I calculate how long "Status1" has been active for?
That is, Substract Row1.[Time]
from Row4.[Time]
, Substract Row8.[Time]
from Row9.[Time]
, Substract Row13.[Time]
from Row15.[Time]
.
Thankyou in advance
Upvotes: 2
Views: 311
Reputation: 77657
The solution by @erikxiv will work if the Row
values have no gaps. If they do have gaps, you could try the following method:
SELECT
TotalDuration = SUM(next.Time - curr.Time)
FROM
dbo.atable AS curr
CROSS APPLY
(
SELECT TOP (1) Time
FROM dbo.atable
WHERE Row > curr.Row
ORDER BY Row ASC
) AS next
WHERE
curr.Status = 'Status1'
;
For every row matching the specified status, the correlated subquery in the CROSS APPLY clause will fetch the next Time
value based on the ascending order of Row
. The current row's time is then subtracted from the next row's time and all the differences are added up using SUM()
.
Please note that in both solutions it is implied that the order of Row
values follows the order of Time
values. In other words, ORDER BY Row
is assumed to be equivalent to ORDER BY Time
or, if Time
can have duplicates, to ORDER BY Time, Row
.
Upvotes: 1
Reputation: 4075
Assuming that each row represents that the specific Status
is active from the specified Time
until the next row, one would have to somehow calculate the difference between row N and N+1. One way would be to use a nested query (try it here: SQL Fiddle).
SELECT SUM(Duration) as Duration
FROM (
SELECT f.Status, s.Time-f.Time as Duration
FROM Table1 f
JOIN Table1 s on s.Row = f.Row+1
WHERE f.Status = 'Status1') a
Upvotes: 2