sql time intervals problem

  • Hi,

    I want to sum the times for each machine state for each shift.

    state0-machine stooped

    state1-machine with alarm

    state2-machine running

    I have table in sql server with next fields:

    Id(int)

    Time_stamp(datetime)

    Machine_state(int)

    I'm tracking machine state which can be 0,1 and 2.

    Now I want to calculate how long machine was in each state in each shift.

    Shifts are 1. 8:00-17:00, 2- 17:00-01:00, 3- 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:

    Example data from table:

    Id, time_stamp, machine_state

    1, 27.3.2009 23:00, 0

    2, 27.3.2009 23:45, 1

    3, 27.3.2009 23:55, 2

    4, 28.3.2009 00:30, 1

    5, 28.3.2009 02:00, 2

    6, 28.3.2009 04:00, 1

    7, 28.3.2009 06:00, 2

    8, 28.3.2009 09:00, 1

    9, 28.3.2009 16:30, 2

    10, 28.3.2009 16:50, 0

    11, 28.3.2009 16:30, 2

    12, 28.3.2009 18:50, 1

    13, 28.3.2009 19:50, 2

    If I use selec form dat1 to date 2 Iā€™ losing time between two shifts, example:

    11, 28.3.2009 16:30, 2

    12, 28.3.2009 18:50, 1

    Shift 2 starts at 17:00, if I select data from 17:00 Iā€™ losing time from 17:00 to 18:50.

    Because with select table I will get data from 18:50ā€¦

    (example, sum_time_1=sum_time_1 + (datediff(s,data12, data13))

    How to get data from 17:00 to 18:50 and how to get machine state in that period(because some part of time between data11 and data12 is in shift1 and some in shift2)

    Please help

    Thanks in advance

    Any idea will help

  • Try something like this:

    create table #T (

    ID int identity primary key,

    Time_stamp datetime,

    Machine_state int);

    insert into #T (Time_stamp, Machine_state)

    select '3.27.2009 23:00', 0 union all

    select '3.27.2009 23:45', 1 union all

    select '3.27.2009 23:55', 2 union all

    select '3.28.2009 00:30', 1 union all

    select '3.28.2009 02:00', 2 union all

    select '3.28.2009 04:00', 1 union all

    select '3.28.2009 06:00', 2 union all

    select '3.28.2009 09:00', 1 union all

    select '3.28.2009 16:30', 2 union all

    select '3.28.2009 16:50', 0 union all

    select '3.28.2009 16:30', 2 union all

    select '3.28.2009 18:50', 1 union all

    select '3.28.2009 19:50', 2;

    create table #Shifts (

    ID int identity primary key,

    SNumber int,

    SStart int,

    SStop int);

    insert into #Shifts (SNumber, SStart, SStop)

    select 1, 8, 17 union all

    select 2, 17, 24 union all

    select 2, 0, 1 union all

    select 3, 1, 8;

    select SNumber as Shift, Machine_State,

    case

    when datepart(hour, State_Start) >= SStart then State_Start

    else dateadd(hour, SStart, dateadd(day, datediff(day, 0, State_Start), 0))

    end as EffectiveStart,

    case

    when datepart(hour, State_End) >= SStop then State_End

    else dateadd(hour, SStop, dateadd(day, datediff(day, 0, State_End), 0))

    end as EffectiveEnd

    from #Shifts Shifts

    inner join

    (select Machine_State, time_stamp as State_Start,

    (select min(time_stamp)

    from #T T2

    where time_stamp > T1.time_stamp

    and Machine_state != T1.Machine_state) as State_End

    from #T T1

    where ID = 11) StartStop

    on SStart >= datepart(hour, State_Start)

    or SStop > datepart(hour, State_End);

    - Gus "GSquared", RSVP, OODA, MAP, NMVP, FAQ, SAT, SQL, DNA, RNA, UOI, IOU, AM, PM, AD, BC, BCE, USA, UN, CF, ROFL, LOL, ETC
    Property of The Thread

    "Nobody knows the age of the human race, but everyone agrees it's old enough to know better." - Anon

  • I didn't know if you wanted to have the amount of time it was in the particular state, and, if so, by what interval (minutes, seconds, hours, etc.), so you'll have to wrap the EffectiveStart and EffectiveEnd columns in a datediff calculation if you want to get that.

    I also have an ID = 11 in the sub-query. That was just for testing one of the rows that crossed a shift boundary. You'll want to remove it to test more of the rows.

    - Gus "GSquared", RSVP, OODA, MAP, NMVP, FAQ, SAT, SQL, DNA, RNA, UOI, IOU, AM, PM, AD, BC, BCE, USA, UN, CF, ROFL, LOL, ETC
    Property of The Thread

    "Nobody knows the age of the human race, but everyone agrees it's old enough to know better." - Anon

  • Thanks on prompt replay(I was thinking that nobody will answer).

    I want to sum time of each state in minutes and group that times by the shifts), but time_stamps sometimes have difference in seconds, so I have to calculate in seconds and on the end transform in minutes.

    so each shift for selected date range(from date1 to date2) will have report with:

    total_alarm_time,

    total_running_time,

    total_stop_time,

    number of alarms(number machine_state=1),

    longest interval of machine running condition(machine_state=2),

    longest interval of machine alarm(machine state=1)

    To have better picture I did export table to access(file in attachment).

    I will wait your advice before I test your code which you did send me in last replay.

    Again many thanks on support.

  • can anybody help!!!:crying:

  • Hi.

    I think this may help....

    select id,

    time_stamp,

    cast(cast(datepart(yyyy,time_stamp) as nvarchar(4))

    +'-'+

    cast(datepart(month,time_stamp) as nvarchar(2))

    +'-'+

    cast(datepart(day,time_stamp) as nvarchar(2))

    +' '+

    cast(datepart(Hour,time_stamp) as nvarchar(2))

    +':'+

    cast(datepart(minute,time_stamp) as nvarchar(2))

    +':00' as datetime) [normalised_TS],

    machine_state

    into #temp

    from export_table

    ----

    -- Running Times Assuming 2 = start and 1 = stop

    ----

    select a.id [startid],

    b.id [stopid],

    a.normalised_TS [starttime],

    a.machine_state [Start],

    b.normalised_TS [endtime],

    b.machine_state [stop],

    datediff(minute,a.normalised_TS,b.normalised_TS) [elapsed_running_minutes]

    into #runningtimes

    from #temp a

    join #temp b

    on b.id = a.id+1

    where a.machine_state = 2

    order by a.id

    ----

    -- Stop Times Assuming 2 = start and 1 = stop

    ----

    select a.id [startid],

    b.id [stopid],

    a.normalised_TS [starttime],

    a.machine_state [Start],

    b.normalised_TS [endtime],

    b.machine_state [stop],

    datediff(minute,a.normalised_TS,b.normalised_TS) [elapsed_running_minutes]

    into #stoptimes

    from #temp a

    join #temp b

    on b.id = a.id+1

    where a.machine_state = 1

    order by a.id

    ----

    -- Create Result sets

    ----

    select 'Max_running_time'[typetime],

    max(elapsed_Running_minutes) [value]

    from #runningtimes

    UNION ALL

    select 'Max_stop_time'[typetime],

    max(elapsed_Running_minutes) [value]

    from #stoptimes

    UNION ALL

    select 'Total_running_time'[typetime],

    sum(elapsed_Running_minutes) [Value]

    from #runningtimes

    UNION ALL

    select 'Total_Stop_time'[typetime],

    sum(elapsed_Running_minutes) [value]

    from #stoptimes

    UNION ALL

    select 'Total_Alarm_count'[typetime],

    count(*)

    from #temp

    where machine_state = '1'

    drop table #temp

    drop table #runningtimes

    drop table #stoptimes

  • I mixed up the statusess... you'll just have to change them accordingly, but I think you get the rough idea what Iw as trying to do...

  • What's up !

    I used GSquared tables for a solution like this:

    -- This is just to create the table for testing.

    create table #MachineStatus (

    ID int identity primary key,

    Time_stamp datetime,

    Machine_state int);

    insert into #MachineStatus (Time_stamp, Machine_state)

    select '3.27.2009 23:00', 0 union all

    select '3.27.2009 23:45', 1 union all

    select '3.27.2009 23:55', 2 union all

    select '3.28.2009 00:30', 1 union all

    select '3.28.2009 02:00', 2 union all

    select '3.28.2009 04:00', 1 union all

    select '3.28.2009 06:00', 2 union all

    select '3.28.2009 09:00', 1 union all

    select '3.28.2009 16:30', 2 union all

    select '3.28.2009 16:50', 0 union all

    select '3.28.2009 16:30', 2 union all

    select '3.28.2009 18:50', 1 union all

    select '3.28.2009 19:50', 2;

    create table #Shifts (

    ID int identity primary key,

    SNumber int,

    SStart int,

    SStop int);

    insert into #Shifts (SNumber, SStart, SStop)

    select 1, 8, 17 union all

    select 2, 17, 24 union all

    select 2, 0, 1 union all

    select 3, 1, 8;

    -- Here is the actual solution.

    ;With StatusFlow

    AS

    (

    SELECT Time_Stamp,

    Machine_State,

    ChangeId = ROW_NUMBER() OVER(ORDER BY Time_Stamp), -- In case the identity gets messed up.

    Shift = SNumber

    FROM #MachineStatusms

    LEFT JOIN #Shifts s ON DATEPART(HOUR,ms.Time_Stamp) BETWEEN s.SStart AND s.SStop

    ),

    Changes AS

    (

    SELECT Status = ss.Machine_State,

    NewStatus = se.Machine_State,

    StateStart = ss.Time_Stamp,

    StateEnd = se.Time_Stamp,

    Duration = DATEDIFF(MINUTE,ss.Time_Stamp, se.Time_Stamp),

    ss.Shift

    FROM StatusFlow ss

    INNER JOIN StatusFlow se ON se.ChangeId = ss.ChangeId + 1

    )

    SELECT Shift,Status, TotalTime = SUM(Duration)

    FROM Changes

    GROUP BY Shift,Status

    ORDER BY Shift ,Status

  • Hey Valkerie,

    It looks like we are really late =S, the post is from 2009 ha ha ha

  • Indeed it does... I just saw the post and posted what I thought would be a possible solution. I like your solution too...

  • Hi,

    thanks on replay(after 3 years)!

    It is very fast!

    In any case I will check this solution, I did make solution for this(with help from SQLServerCentral) and it is running stable for 3 years.

    I'm collecting time stamps about machine states from 10 machines over OPC server and store that to SQL server.

    Than ERP send request to SQL to calculate how much machine was running/stooped from some time frame.

    Is runs perfectly for 3 years(no bug).

    Thanks on your wish to help!

    Thanks

  • Thank you Valkeri =D

  • You project is nice,

    how does your ERP gets your data?.

    By the way , im kindof Arduino fan, i like machine things too =D, but im not a master.

  • Hi,

    In production we have labeling system with scanners which counts the produced products.

    On end of each shift ERP collect data about produced quantity's from labeling system and in same time collect data from SQL server(SQL gets data over OPC and DataHub)

    about time when machine was running and stooped.

    So on the end in ERP we have machine/shift productivity.

    -machine down time

    -machine running time

    -average machine running speed(products/min)

    -machine alarm time(how much of time machine was in alarm state)

    All this is happening full automatically.

    From all of this in ERP we get very powerful reports which we use to mark the shifts and adjust salary accordingly.

    Thanks

Viewing 14 posts - 1 through 13 (of 13 total)

You must be logged in to reply to this topic. Login to reply