Reputation: 13
I have a workflow application where the workflow is written to the DB as shown below when the status changes. There is no end time as it is a sequence of events. I want to create a query that will group by the WorkFlowID and total the amount of time spent in each. I am not sure how to even begin
My table and data looks like this
+------------+---------------------+ | WorkFlowID | EventTime | +------------+---------------------+ | 1 | 07/15/2015 12:00 AM | | 2 | 07/15/2015 12:10 AM | | 3 | 07/15/2015 12:20 AM | | 2 | 07/15/2015 12:30 AM | | 3 | 07/15/2015 12:40 AM | | 4 | 07/15/2015 12:50 AM | +------------+---------------------+
My end result should be like:
+------------+-----------------+ | WorkFlowID | TotalTimeInMins | +------------+-----------------+ | 1 | 10 | | 2 | 20 | | 3 | 20 | | 4 | 10 | +------------+-----------------+
Upvotes: 0
Views: 1203
Reputation: 40359
The basis of a method that works in all (ok, I don't know about SQL 6.5) editions is to use the group by
clause:
SELECT
WorkFlowID
,datediff(mi, min(EventTime), max(EventTime)) TotalTimeInMins
from MyTable
group by WorkFlowID
This does indeed leave the question of how you got 10 minutes with a start time and (presumably) no end time. As written, this query would list the WorkFlowID with TotalTimeInMins = 0, which seems accurate enough. The following variant would remove all "start-only" items:
SELECT
WorkFlowID
,datediff(mi, min(EventTime), max(EventTime)) TotalTimeInMins
from MyTable
group by WorkFlowID
having count(*) > 1
(The quick explanation: having
is to group by
as where
is to from
)
Upvotes: 0
Reputation: 16968
As an alternative:
;WITH t AS (
SELECT *,
ROW_NUMBER() OVER (ORDER BY EventTime) As rn
FROM
yourTable)
SELECT
t1.WorkFlowID,
SUM(DATEDIFF(SECOND, t1.EventTime, ISNULL(t2.EventTime, GETDATE()) / 60) As TotalTimeInMins
FROM t t1
LEFT JOIN t t2
ON t1.rn = t2.rn - 1
Upvotes: 0
Reputation: 1270493
In SQL Server 2012+, you would just use lead()
. There are several ways to approach this in SQL Server 2008. Here is one using `outer apply:
select t.WorkFlowId,
sum(datediff(second, EventTime, nextTime)) / 60.0 as NumMinutes
from (select t.*, t2.EventTime as nextTime
from table t outer apply
(select top 1 t2.*
from table t2
where t2.EventTime > t.EventTime
order by t2.EventTime
) t2
) tt
group by t.WorkFlowId;
The only question is how you get "10" for event 4. There is no following event, so that value doesn't make sense. You can use datediff(second, EventTime coalesce(NextEvent, getdate())
to handle the NULL
value.
Upvotes: 1