I'm tracking machine state which can be 0,1 and 2, and storing that data in sql table with time_stamp. I have table in sql server with next fields: id(int) time_stamp(datetime) machine_state(int)
Machine state is connected with machine condition:
machine_state =0 -machine stooped
machine_state =1-machine with alarm
machine_state =2-machine running
Now I want to calculate how long machine was in each state in each shift. Shifts are
- 8:00-17:00
- 17:00-01:00
- 01:00-08:00.
My problem is how I can calculate time of each state of machine(sum_time_0, sum_time_1, sum_time_2) and group that times by the shift. I want to calculate time in seconds and then convert to minutes.
To have better picture I did export part of table
EXPORT_TABLE
id time_stamp machine_state
1623 6.10.2009 17:09:00 1
1624 6.10.2009 17:17:00 2
1625 6.10.2009 17:17:00 1
1626 6.10.2009 17:17:00 2
1627 6.10.2009 17:18:00 1
1628 6.10.2009 17:18:00 2
1629 6.10.2009 18:04:00 1
1630 6.10.2009 18:06:00 2
1631 6.10.2009 18:07:00 1
1632 6.10.2009 18:12:00 2
1633 6.10.2009 18:28:00 1
1634 6.10.2009 18:28:00 2
1635 6.10.2009 19:16:00 1
1636 6.10.2009 19:21:00 2
1637 6.10.2009 19:49:00 1
1638 6.10.2009 20:23:00 2
Any advice will help. Thanks in advance.
You can join the next machine state for each row then group by the state and sum the difference in time...
Here's an outline of how I'd do it. I am making some assumptions which may be invalid or not apply to your situation, so I'm not coding everything out.
First, I'd break the problem into chunks: calculate the data for one shift at a time. (I'm guessing you run this once a day, or maybe once a week.)
I would implement this as a stored procedure with two parameters:
Build two "full" datetimes, one for the start of the shift, one for the end. For example, if @ShiftDate = 'Oct 22, 2009' and @Shift = 2, you'd get
Create a temp table to hold the subset of the data that we'll be analyzing. Populate it like so:
Next, check if entries are present for both @ShiftStart and @ShiftStop. If there are no such entries:
You need these entries to get the data for the time between the start of the shift and the first recorded entry within that shift, and ditto for the end of the shift.
At this point, items are ordered in time, with a uniformly incrementing counter column (1, 2, 3). Assuming all the above, the following query should return the data you're looking for:
Notes:
EXPORT_TABLE is the temporary table described above.
This is just a framework. I think you'd be able to exapnd this to whatever conditions you have to deal with.
If you just want quick and dirty, this will do:
And go from there.
But this method, and some of the similar methods on this page involving a non-equijoin, will not scale well with volume. To handle a high volume of data, we must use different techniques.
Your id appears sequential. Is it? This can be useful. If not, we should create one.
Once we have a sequential id, we can equi-join on it:
From here, your query should just about write itself. Look out for machine states that overlap a shift, though.
This method, though it looks expensive, will scale well with volume. You order the data once, and join once. If the id is sequential, you can skip the first step, make sure there is a clustered primary key on id, and join on id rather than seqno.
If you have a really high volume of data, you do this instead:
This will out-perform all other methods. And if your id is in the right order (it does not have to be sequential, just in the right order), you can skip the first step and define a clustered index on id instead, if it's not already there.
You can do smth like this:
This will return you the interval in one row, after that it's easy to calculate cumulative time for each state.
You can also look at this question. It seems to be almost similar to yours.
thanks on help. I surprised how detail is the answer. I will tests you solution and inform you about result. Again I'm very surprised with detail answer.
I did test first part(to sum time of machine state 0, 1 i 2) and this is OK. Now I will test rest part of the answer.
Biggest problem for me was time splitting during shift transition. example: '6.10.2009 16:30:00', 1 '6.10.2009 17:30:00', 2 '6.10.2009 19:16:00', 1
In time between 16:30 and 17:00 machine was in state 1 and that time I have to add to shift 1, and time between 17:00 and 17:30 machine was in state 1 and that time I have to add to shift 2.
But first I will go through you answer to see did you already make solution for this.
thanks again