Reputation: 465
I'm tracking machines and the amount of time they spend in various states with the following query:
select ks.CalendarId
, ks.machineid
, ks.machinestateid
, lead(ks.machinestateid) over (partition by ks.machineid, ks.calendarid order by ks.machinefmstatetime desc) prevstateid
, ks.machinestatehistoryid
, ks.machinefmstatetime
, ks.StateTimeInSeconds
, sum(ks.statetimeinseconds) over (partition by ks.machineid, ks.calendarid, ks.machinestateid order by ks.machinefmstatetime) StateTimeSecTotal
from [dbo].[MachineStateDailyDistributionFact] ks
where calendarid in (20180425)
and ks.machineid in (38141)
order by ks.MachineFmStateTime
This is all good except for StateTimeSecTotal. When a machine goes back into a state that it was in sometime prior, the StateTimeSecTotal picks up where it left off. I need the second count to "start over".
For example in the below pic, I need the highlighted cell to be 0, and then proceed to count up as it already is.
How do I change my query to have total state duration "start over" when in a different "state block of time"?
thanks for any tips, sff
Upvotes: 1
Views: 135
Reputation: 1270653
You have a gaps-and-islands problem. Here is a solution using row_number()
:
select . . .,
sum(ks.statetimeinseconds) over (partition by ks.machineid, ks.calendarid, ks.machinestateid order by ks.machinefmstatetime) StateTimeSecTotal
select . . .,
sum(ks.statetimeinseconds) over (partition by ks.machineid, ks.calendarid, ks.machinestateid, seqnum_1-seqnum_2 order by ks.machinefmstatetime) StateTimeSecTotal
from (select ks.*,
row_number() over (partition by ks.machineid, ks.calendarid order by ks.machinefmstatetime) as seqnum_1,
row_number() over (partition by ks.machineid, ks.calendarid, ks.machinestateid order by ks.machinefmstatetime) as seqnum_2
from [dbo].[MachineStateDailyDistributionFact] ks
where calendarid in (20180425) and ks.machineid in (38141)
) ks
order by ks.MachineFmStateTime;
The difference of row numbers identifies the adjacent groups of machine id states.
Upvotes: 1